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).