Bagaimana cara membuat file ke ukuran yang diinginkan?

15

Saya memiliki file yang ingin saya pad hingga mencapai 16 MiB (16777216 bytes). Saat ini adalah 16515072 byte. Perbedaannya adalah 262144 byte.

Bagaimana saya memasangnya?

Ini sepertinya tidak berfungsi:

cp smallfile.img largerfile.img
dd if=/dev/zero of=largerfile.img bs=1 count=262144
tarabyte
sumber
2
@terabyte; Anda ingin lapisan fisik atau lapisan logis? Dengan kata lain; haruskah file hanya menampilkan ukuran 16777216 (dan mungkin mengandung lubang) atau haruskah itu juga menempati jumlah penyimpanan pada disk? - BTW, memilih bs=1dalam ddadalah pengalaman saya sangat runtime mahal.
Janis
5
truncate -s 16M thefile
frostschutz
4
@ frostschutz itu akan menjadi jawaban yang baik, apakah Anda mempostingnya sebagai jawaban.
derobert
@derobert, Ada apa dengan pengguna situs StackExchange yang memposting jawaban yang sah dan sederhana sebagai komentar?
user1717828
@ user1717828 tidak yakin, mungkin pertanyaan yang bagus untuk meta.
derobert

Jawaban:

10

Letakkan of=largerfile.txtdan tambahkan stdout ke file:

dd if=/dev/zero bs=1 count=262144 >> largerfile.txt
Mengungguli
sumber
1
seekadalah opsi yang tepat di sini.
0andriy
15

Selain jawaban untuk mendapatkan padding fisik Anda juga dapat meninggalkan sebagian besar ruang padding dalam file hanya kosong ("lubang"), dengan seekmemasukkan ke posisi akhir file yang baru dan menulis satu karakter:

dd if=/dev/zero of=largerfile.txt bs=1 count=1 seek=16777215

(yang memiliki keuntungan untuk menjadi jauh lebih performan, khususnya dengan bs=1, dan tidak menempati sejumlah besar ruang disk tambahan).

Metode itu tampaknya berfungsi bahkan tanpa menambahkan karakter apa pun, dengan menggunakan if=/dev/nulldan ukuran file akhir yang diinginkan:

dd if=/dev/null of=largerfile.txt bs=1 count=1 seek=16777216

Varian performan dari solusi pelapis fisik yang menggunakan ukuran blok yang lebih besar adalah:

padding=262144 bs=32768 nblocks=$((padding/bs)) rest=$((padding%bs))
{
  dd if=/dev/zero bs=$bs count=$nblocks
  dd if=/dev/zero bs=$rest count=1
} 2>/dev/null >>largerfile.txt
Janis
sumber
3
Benar. Dalam hal ini truncate -s +262144 largerfile.txtjuga akan cepat.
don_crissti
4

Browser terbaik di sini adalah Janis (di atas) karena memungkinkan Anda melupakan ukuran file saat ini dan pad langsung ke ukuran yang diinginkan tanpa perhitungan.

Itu juga mengambil keuntungan dari file jarang, yang menambahkan / dev / nol tidak.

Jawabannya bisa lebih rapi, karena 'hitung' diizinkan 0 dan Anda masih mendapatkan lapisan:

dd if=/dev/null of=largerfile.txt bs=1 count=0 seek=16777216

(Edit: ini benar untuk GNU dd, tetapi perilaku count=0spesifik platform, lihat komentar)

PeteC
sumber
Anda salah: count=0tidak ditentukan, tetapi biasanya sama seperti ketika tidak ada countparameter yang ditentukan. Lebih banyak masalah: ddmemotong file ke 16777216 byte, tetapi jika Anda berharap ini membuat lubang di akhir, Anda salah karena Anda pertama-tama harus menulis data setelah lubang dan kemudian memotongnya ke ukuran yang tidak mengandung data. .
schily
count = 0 tidak seperti menspesifikasikan parameter no count. Apakah Anda mengatakan itu dd if=/dev/zero of=somefilesama dd if=/dev/zero of=somefile count=0? Cobalah.
PeteC
Tentu saja! count=0 adalah sama seperti jika Anda tidak menentukan parameter hitungan sama sekali. Ini berlaku setidaknya untuk semua implementasi yang berasal dari sumber asli. Coba saja, sepertinya Anda tidak pernah bekerja dengan ddperintah aslinya .
schily
Saya tidak dapat menemukan dokumentasi yang menetapkan 0 sebagai nilai unik untuk countmakna 'abaikan parameter ini'. Bisakah kamu menemukan? Tanpa dokumentasi seperti itu, count=0berarti 'tulis nol blok' dan penyimpangan dari ini adalah bug ... (sumber asli atau tidak ada).
PeteC
1
Ini adalah dokumentasi POSIX dari sebelum Mei 2015 ketika teks yang kurang ditentukan diperbaiki.
schily
1

Apakah Anda harus menggunakan dd? Jika Anda ingin file memiliki panjang (logis) tertentu, cukup tulis nol ke posisi yang Anda inginkan. Bytes antara ujung sebelumnya dan byte tertulis akan ditampilkan sebagai byte nol. Berikut ini contoh menggunakan perl.

$ echo Hello > file
$ ls -l file
-rw-r--r-- 1 user group 6 Apr 16 22:59 file
$ perl -le 'open(my $f,"+<","file"); seek($f, 16777216 - 2, 0); print $f "\0"'
$ ls -ln file
-rw-r--r-- 1 user group 16777216 Apr 16 22:59 file

Mengapa "- 2" di baris? Script akan menulis byte, jadi kita kurangi 1 untuk mencari ke posisi sebelum byte itu. Kami melepas yang lain karena posisi pencarian nol-diindeks.

BowlOfRed
sumber