¿Cómo rellenar un archivo al tamaño deseado?

15

Tengo un archivo que quiero rellenar hasta que llegue a 16 MiB (16777216 bytes). Actualmente es 16515072 bytes. La diferencia es 262144 bytes.

¿Cómo lo relleno?

Esto no parece estar funcionando:

cp smallfile.img largerfile.img
dd if=/dev/zero of=largerfile.img bs=1 count=262144
tarabyte
fuente
2
@terabyte; ¿Quieres relleno físico o relleno lógico? En otras palabras; ¿el archivo solo debe mostrar un tamaño de 16777216 (y puede contener agujeros) o también debe ocupar esa cantidad de almacenamiento en el disco? - Por cierto, la elección de una bs=1en ddestá en mi experiencia muy costosa en tiempo de ejecución.
Janis
55
truncate -s 16M thefile
frostschutz
44
@frostschutz, esa sería una buena respuesta, si la publicaras como respuesta.
derobert
@derobert, ¿Qué pasa con los usuarios del sitio StackExchange que publican respuestas simples y legítimas como comentarios?
user1717828
@ user1717828 no estoy seguro, probablemente sea una buena pregunta para meta.
derobert

Respuestas:

10

Suelta of=largerfile.txty agrega stdout al archivo:

dd if=/dev/zero bs=1 count=262144 >> largerfile.txt
Outurnate
fuente
1
seekEs una opción correcta aquí.
0andriy
15

Además de las respuestas para obtener un relleno físico, también puede dejar la mayor parte del espacio de relleno en el archivo simplemente vacío ("agujeros"), seekyendo a la nueva posición final del archivo y escribiendo un solo carácter:

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

(que tiene la ventaja de ser mucho más eficiente, específicamente con bs=1, y no ocupa grandes cantidades de espacio en disco adicional).

Ese método parece funcionar incluso sin agregar ningún carácter, mediante el uso if=/dev/nully el tamaño final deseado del archivo:

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

Una variante eficaz de una solución de relleno físico que utiliza bloques de mayor tamaño es:

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
fuente
3
Correcto. En este caso truncate -s +262144 largerfile.txttambién sería rápido.
don_crissti
4

La mejor respuesta aquí es la de Janis (arriba) porque le permite olvidarse del tamaño del archivo actual y el pad directamente al tamaño deseado sin ningún cálculo.

También aprovecha los archivos dispersos, que no se agregan / dev / zero.

Sin embargo, la respuesta podría ser más ordenada, porque 'count' puede ser 0 y aún obtienes el relleno:

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

(Editar: esto es correcto para GNU dd, pero el comportamiento de count=0es específico de la plataforma, ver comentarios)

PeteC
fuente
Está equivocado: count=0no está especificado, pero normalmente es el mismo que cuando no countse especificó ningún parámetro. Más problemas: ddtrunca el archivo a 16777216 bytes, pero si tiene la esperanza de que esto cree un agujero al final, está equivocado ya que primero necesitaría escribir datos después del agujero y luego truncarlo a un tamaño que no contenga datos .
schily
count = 0 no es como especificar ningún parámetro de conteo. ¿Estás diciendo que dd if=/dev/zero of=somefilees lo mismo que dd if=/dev/zero of=somefile count=0? Intentalo.
PeteC
¡Por supuesto! count=0 es lo mismo que si no especificaras un parámetro de conteo en absoluto. Esto es cierto al menos para todas las implementaciones que se han derivado de las fuentes originales. Pruébelo, parece que nunca trabajó con el ddcomando original .
schily
No puedo encontrar ninguna documentación que especifique 0 como un valor único para countsignificar 'ignorar este parámetro'. ¿Puedes encontrar alguno? Sin dicha documentación, count=0significa 'escribir cero bloques' y cualquier desviación de esto es un error ... (fuentes originales o no).
PeteC
1
Esta fue la documentación POSIX de antes de mayo de 2015 cuando se corrigió el texto no especificado.
schily
1

¿Tienes que usar dd? Si desea que un archivo tenga una longitud (lógica) particular, simplemente escriba un cero en la posición que desea. Los bytes entre el final anterior y el byte escrito se mostrarán con bytes nulos. Aquí hay un ejemplo usando 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

¿Por qué el "- 2" en la línea? El script escribirá un byte, por lo que restamos 1 para buscar la posición anterior a ese byte. Despegamos el otro porque la posición de búsqueda está indexada a cero.

BowlOfRed
fuente