dd: múltiples archivos de entrada

14

Necesito concatenar fragmentos de dos archivos:

si necesitaba concatenar archivos completos, simplemente podría hacer

cat file1 file2 > output

Pero necesito omitir el primer 1 MB del primer archivo, y solo quiero 10 MB del segundo archivo. Suena como un trabajo para dd.

dd if=file1 bs=1M count=99 skip=1 of=temp1
dd if=file2 bs=1M count=10 of=temp2
cat temp1 temp2 > final_output

¿Existe la posibilidad de hacer esto en un solo paso? es decir, sin la necesidad de guardar los resultados intermedios? ¿Puedo usar múltiples archivos de entrada dd?

Martin Vegter
fuente

Respuestas:

21

dd puede escribir a stdout también.

( dd if=file1 bs=1M count=99 skip=1
  dd if=file2 bs=1M count=10  ) > final_output
meuh
fuente
Esta es probablemente la mejor manera. El archivo de salida no se cierra / vuelve a abrir (como oflag=append conv=notruncocurre con ), por lo que es menos probable que los sistemas de archivos que realizan una asignación retrasada (como XFS) decidan que el archivo se termine de escribir cuando aún queda más.
Peter Cordes
@PeterCordes es un buen punto, pero siempre que ddno se solicite sync, la asignación retrasada no debería activarse inmediatamente de todos modos (a menos que la memoria sea escasa, en cuyo caso ninguno de los métodos pospondrá la asignación).
Stephen Kitt
@StephenKitt: Probablemente tengas razón. Estaba pensando en la preasignación especulativa de XFS , donde necesita detectar especialmente el patrón de acceso de cierre / reapertura (a veces visto para archivos de registro).
Peter Cordes
3
En shells como bashy mkshque no optimizan la bifurcación para el último comando en una subshell, puede hacerlo un poco más eficiente reemplazando la subshell con un grupo de comandos. Para otros shells, no debería importar, y el enfoque de subshell podría incluso ser un poco más eficiente ya que el shell no necesita guardar y restaurar stdout.
Stéphane Chazelas
10

No creo que pueda leer fácilmente varios archivos en una sola ddinvocación, pero puede agregar para construir el archivo de salida en varios pasos:

dd if=file1 bs=1M count=99 skip=1 of=final_output
dd if=file2 bs=1M count=10 of=final_output oflag=append conv=notrunc

Necesita especificar ambos conv=notruncy oflag=append. El primero evita truncar la salida, el segundo comienza a escribir desde el final del archivo existente.

Stephen Kitt
fuente
8

Tenga en cuenta que ddes una interfaz prima hasta el read(), write()y lseek()la llamada al sistema. Solo puede usarlo de manera confiable para extraer fragmentos de datos de archivos normales, bloquear dispositivos y algunos dispositivos de caracteres (como /dev/urandom), es decir, archivos para los que read(buf, size)se garantiza que regresará sizesiempre que no se llegue al final del archivo.

Para tuberías, tomas de corriente y la mayoría de los dispositivos de caracteres (como ttys), no tiene esa garantía a menos que lo haga read()de tamaño 1, o use la ddextensión GNU iflag=fullblock.

Entonces:

{
  gdd < file1 bs=1M iflag=fullblock count=99 skip=1
  gdd < file2 bs=1M iflag=fullblock count=10
} > final_output

O:

M=1048576
{
  dd < file1 bs=1 count="$((99*M))" skip="$M"
  dd < file2 bs=1 count="$((10*M))"
} > final_output

O con proyectiles con soporte incorporado para un operador de búsqueda como ksh93:

M=1048576
{
  command /opt/ast/bin/head -c "$((99*M))" < file1 <#((M))
  command /opt/ast/bin/head -c "$((10*M))" < file2
}

O zsh(suponiendo que su headsoporte sea la -copción aquí):

zmodload zsh/system &&
{
  sysseek 1048576 && head -c 99M &&
  head -c 10M < file2
} < file1 > final_output
Stéphane Chazelas
fuente
¿Realmente necesitas las citas? ¿El resultado no será siempre un entero?
Steven Penny
@StevenPenny, dejar la expansión sin comillas es pedirle al shell que se divida + glob, lo que no tendría ningún sentido aquí. La parte dividida que se realiza en el valor actual de $IFS. Eso es independientemente del contenido de la variable / expansión. Consulte también Implicaciones de seguridad de olvidarse de citar una variable en shells bash / POSIX
Stéphane Chazelas
@ Stéphane Chazelas: en el primer ejemplo, está utilizando en gddlugar de dd. ¿Es un error tipográfico o es intencional?
Martin Vegter
3

Con un bash ism y funcionalmente "uso inútil de cat ", pero más cercano a la sintaxis que usa el OP:

cat <(dd if=file1 bs=1M count=99 skip=1) \
    <(dd if=file2 bs=1M count=10) \
   > final_output

(Dicho esto, la respuesta de Stephen Kitt parece ser el método más eficiente posible).

agc
fuente
3
Estrictamente hablando, <(...)es un kshismo que tanto zshy bashcopiado.
Stéphane Chazelas