dd: múltiples files de input

Necesito concatenar fragments de dos files:

si necesitaba concatenar files completos, simplemente podría hacer

cat file1 file2 > output 

Pero necesito saltear primero 1MB del primer file, y solo quiero 10 MB del segundo file. 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 save los resultados intermedios? ¿Puedo usar múltiples files de input en dd ?

dd puede escribir en stdout.

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

No creo que pueda leer fácilmente varios files en una sola invocación dd , pero puede anexar para comstackr el file 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 

conv=notrunc especificar tanto conv=notrunc como oflag=append . El primero evita truncar el resultado, el segundo comienza a escribir desde el final del file existente.

Tenga en count que dd es una interfaz en bruto para las llamadas al sistema read() , write() y lseek() . Solo puede usarlo de manera confiable para extraer fragments de datos de files normales, dispositivos de locking y algunos dispositivos de caracteres (como /dev/urandom ), es decir, files para los que se garantiza que la read(buf, size) devolverá size siempre que el final del file no se alcanza.

Para tuberías, sockets y la mayoría de los dispositivos de caracteres (como ttys), no tiene esa garantía a less que read() s de tamaño 1, o use la extensión GNU dd iflag=fullblock .

Entonces o bien:

 { 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 shells con soporte integrado 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 head admita la opción -c aquí):

 zmodload zsh/system && { sysseek 1048576 && head -c 99M && head -c 10M < file2 } < file1 > final_output 

Con un bashismo , y un uso funcionalmente "inútil del gato ", pero más cercano a la syntax que utiliza 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).