Jak uzupełnić plik do pożądanego rozmiaru?

15

Mam plik, który chcę wypełnić, aż osiągnie 16 MiB (16777216 bajtów). Obecnie jest to 16515072 bajtów. Różnica wynosi 262144 bajtów.

Jak to zrobić?

To nie wydaje się działać:

cp smallfile.img largerfile.img
dd if=/dev/zero of=largerfile.img bs=1 count=262144
tarabajt
źródło
2
@terabyte; chcesz dopełnienie fizyczne czy logiczne? Innymi słowy; czy plik powinien pokazywać tylko rozmiar 16777216 (i może zawierać dziury), czy też powinien również zajmować taką ilość miejsca na dysku? - Przy okazji, wybierając bs=1in ddjest w moim doświadczeniu bardzo Runtime drogie.
Janis
5
truncate -s 16M thefile
frostschutz
4
@frostschutz to byłaby dobra odpowiedź, gdybyś opublikował ją jako odpowiedź.
derobert
@derobert, Co z użytkownikami serwisu StackExchange publikującymi proste, proste odpowiedzi jako komentarze?
user1717828,
@ user1717828 nie jestem pewien, prawdopodobnie dobre pytanie do meta.
derobert

Odpowiedzi:

10

Upuść of=largerfile.txti dołącz stdout do pliku:

dd if=/dev/zero bs=1 count=262144 >> largerfile.txt
Outurnate
źródło
1
seekjest tutaj właściwą opcją.
0andriy
15

Oprócz odpowiedzi, aby uzyskać fizyczne wypełnienie, możesz również pozostawić większość miejsca wypełniania w pliku po prostu puste („dziury”), seekprzechodząc do nowej pozycji końcowej pliku i wpisując pojedynczy znak:

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

(co ma tę zaletę, że jest znacznie wydajniejsze, szczególnie z bs=1, i nie zajmuje dużej ilości dodatkowego miejsca na dysku).

Ta metoda wydaje się działać nawet bez dodawania żadnego znaku, przy użyciu if=/dev/nulli końcowej żądanej wielkości pliku:

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

Wydajny wariant fizycznego wypełnienia, który wykorzystuje większe rozmiary bloków, to:

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
źródło
3
Poprawny. W tym przypadku truncate -s +262144 largerfile.txtbyłoby również szybko.
don_crissti
4

Najlepszą odpowiedzią jest tutaj Janis (powyżej), ponieważ pozwala zapomnieć o bieżącym rozmiarze pliku i wpisać bezpośrednio żądany rozmiar bez obliczeń.

Wykorzystuje także rzadkie pliki, których nie dołącza / dev / zero.

Odpowiedź może być bardziej uporządkowana, ponieważ „count” może wynosić 0, a Ty wciąż dostajesz dopełnienie:

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

(Edycja: jest to poprawne dla GNU dd, ale zachowanie count=0jest specyficzne dla platformy, patrz komentarze)

PeteC
źródło
Mylisz się: count=0jest nieokreślony, ale zazwyczaj jest taki sam jak wtedy, gdy nie countokreślono żadnego parametru. Więcej problemów: ddobcina plik do 16777216 bajtów, ale jeśli masz nadzieję, że spowoduje to powstanie dziury na końcu, mylisz się, ponieważ najpierw musisz zapisać dane po dziurze, a później przyciąć go do rozmiaru, który nie zawiera danych .
schily
count = 0 to nic innego jak określenie parametru no count. Mówisz, że dd if=/dev/zero of=somefileto to samo co dd if=/dev/zero of=somefile count=0? Spróbuj.
PeteC,
Oczywiście! count=0 jest taki sam, jakby w ogóle nie określono parametru count. Dotyczy to przynajmniej wszystkich implementacji pochodzących z oryginalnych źródeł. Spróbuj, wygląda na to, że nigdy nie pracowałeś z oryginalnym ddpoleceniem.
schily,
Nie mogę znaleźć żadnej dokumentacji, która określa 0 jako unikalną wartość countoznaczającą „zignoruj ​​ten parametr”. Czy możesz znaleźć Bez takiej dokumentacji count=0oznacza „napisz zero bloków”, a każde odchylenie od tego jest błędem ... (oryginalne źródła lub nie).
PeteC,
1
Była to dokumentacja POSIX sprzed maja 2015 r., Kiedy nieokreślony tekst został poprawiony.
schily
1

Czy musisz użyć dd? Jeśli chcesz, aby plik miał określoną (logiczną) długość, po prostu wpisz zero w wybranej pozycji. Bajty między poprzednim końcem a bajtem zapisanym będą wyświetlane jako bajty puste. Oto przykład użycia perla.

$ 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

Dlaczego „- 2” w linii? Skrypt napisze bajt, więc odejmujemy 1, aby wyszukać pozycję przed tym bajtem. Zdejmujemy drugą, ponieważ pozycja szukania jest zerowana.

BowlOfRed
źródło