¿Cuál es la mejor manera de unir archivos nuevamente después de dividirlos?

73

Si tengo un archivo grande y necesito dividirlo en fragmentos de 100 megabytes, lo haré

split -b 100m myImage.iso

Eso generalmente me da algo como

xaa
xab
xac
xad

Y para volverlos a juntar he estado usando

cat x* > myImage.iso

Parece que debería haber una forma más eficiente que leer cada línea de código en un grupo de archivos caty redirigir la salida a un nuevo archivo. Como una forma de abrir dos archivos, quitar el EOFmarcador del primero y conectarlos, sin tener que revisar todo el contenido.

Windows / DOS tiene un comando de copia para archivos binarios. La ayuda menciona que este comando fue diseñado para poder combinar múltiples archivos. Funciona con esta sintaxis: ( /bes para modo binario)

copy /b file1 + file2 + file3 outputfile

¿Hay algo similar o una mejor manera de unir archivos grandes en Linux que cat?

Actualizar

Parece que catde hecho es la forma correcta y la mejor manera de unir archivos. Me alegra saber que estaba usando el comando correcto todo el tiempo :) Gracias a todos por sus comentarios.

cwd
fuente
22
Nota al margen: es mejor no usar cat x*, porque el orden de los archivos depende de la configuración regional. Mejor comience a escribir cat x, que presione Esc y luego *, verá el orden ampliado de los archivos y podrá reorganizarlos.
rozcietrzewiacz
16
En lugar de cat x*considerar la expansión de la abrazadera de concha, cat xa{a..g}que expande la secuencia especificada a cat xaa xab xac xad xae xaf xag
Peter.O
3
@rozcietrzewiacz: ¿puede dar un ejemplo de cómo ajustaría mi configuración regional que se rompería cat x*? Sería la nueva configuración regional no que también afectan splitde manera que si splity cat x*se utilizaron en el mismo sistema que siempre iba a funcionar?
cwd
3
"abrir dos archivos, eliminar el marcador EOF del primero y conectarlos, sin tener que pasar por todo el contenido" ... parece que necesita inventar un nuevo sistema de archivos para hacer lo que quiere
JoelFan
66
@cwd: Mirando split.cen Coreutils GNU, los sufijos se construyen a partir de una matriz fija de caracteres: static char const *suffix_alphabet = "abcdefghijklmnopqrstuvwxyz";. El sufijo no se vería afectado por la configuración regional. (Pero yo no creo que ningún local en su sano juicio reordenar las letras minúsculas, incluso EBCDIC mantiene su orden natural.)
Keith Thompson

Respuestas:

50

Para eso catestá hecho. Dado que es una de las herramientas GNU más antiguas, creo que es muy poco probable que cualquier otra herramienta lo haga más rápido / mejor. Y no es tubería , solo redirige la salida.

rozcietrzewiacz
fuente
El cat x, then press Esctruco que mencionaste es bueno ... He estado buscando algo así, gracias ... buen comentario y buena respuesta
Peter.O
2
De nada :) Además, cuando tenga esa lista de archivos en la línea de comandos, puede usar Ctrl+Wpara cortar una palabra y luego Ctrl+Ypegarla.
rozcietrzewiacz
gato significa "concatenar"
JoelFan
44
.. y "catenate" derivadas de una palabra latina "catena" que significa "una cadena" .. concatenar es unir los eslabones de una cadena. ... (y un poco más fuera de tema, una curva de catenaria también se deriva de "catena". Es la forma en que cuelga una cadena)
Peter.O
19

Bajo el capó

No hay una forma más eficiente que copiar el primer archivo, luego copiar el segundo archivo después, y así sucesivamente. Tanto DOS copycomo cateso.

Cada archivo se almacena independientemente de otros archivos en el disco. Casi todos los sistemas de archivos diseñados para almacenar datos en un dispositivo similar a un disco funcionan por bloques. Aquí hay una presentación muy simplificada de lo que sucede: el disco se divide en bloques de, digamos 1kB, y para cada archivo el sistema operativo almacena la lista de bloques que lo componen. La mayoría de los archivos no tienen un número entero de bloques largos, por lo que el último bloque solo está parcialmente ocupado. En la práctica, los sistemas de archivos tienen muchas optimizaciones, como compartir el último bloque parcial entre varios archivos o almacenar "bloques 46798 a 47913" en lugar de "bloque 46798, bloque 46799, ...". Cuando el sistema operativo necesita crear un nuevo archivo, busca bloques libres. Los bloques no tienen que ser consecutivos: si solo los bloques 4, 5, 98 y 178 son gratuitos, aún puede almacenar un archivo de 4kB.

Podría admitir bloques parciales en el medio del archivo, pero eso agregaría una complejidad considerable, particularmente al acceder a archivos de forma no secuencial: para saltar al byte 10340, ya no podría saltar al byte 100 del bloque 11, tendría que para verificar la longitud de cada bloque intermedio.

Dado el uso de bloques, no puede simplemente unir dos archivos, porque en general el primer archivo termina a mitad de bloque. Claro, podría tener un caso especial, pero solo si desea eliminar ambos archivos al concatenar. Eso sería un manejo altamente específico para una operación rara. Tal manejo especial no vive solo, porque en un sistema de archivos típico, se accede a muchos archivos al mismo tiempo. Entonces, si desea agregar una optimización, debe pensar cuidadosamente: ¿qué sucede si algún otro proceso está leyendo uno de los archivos involucrados? ¿Qué sucede si alguien intenta concatenar A y B mientras alguien concatena A y C? Y así. En general, esta rara optimización sería una carga enorme.

Con todo, no puede hacer que la unión de archivos sea más eficiente sin hacer grandes sacrificios en otro lugar. Que no vale la pena.

Sobre dividir y unir

splity catson formas simples de dividir y unir archivos. splitse encarga de producir archivos nombrados en orden alfabético, por lo que cat *funciona para unirse.

Una desventaja de catunirse es que no es robusto frente a los modos de falla comunes. Si uno de los archivos está truncado o falta, catno se quejará, solo obtendrá un resultado dañado.

Hay utilidades de compresión que producen archivos de varias partes, como zipsplity rar -v. No son muy unixy, porque comprimen y empaquetan (ensamblan varios archivos en uno) además de dividir (y viceversa descomprimir y descomprimir además de unir). Pero son útiles porque verifican que tiene todas las partes y que las partes están completas.

Gilles 'SO- deja de ser malvado'
fuente
8

Parece que debería haber una forma más eficiente que canalizar todo el contenido a través del sistema stdin/stdout

Excepto que eso no es realmente lo que está sucediendo. El shell está conectando la salida estándar cat directamente al archivo abierto, lo que significa que "pasar por salida estándar" es lo mismo que escribir en el disco.

Ignacio Vazquez-Abrams
fuente
Estaba imaginando usar cat para mostrar varios gigabytes de código en la consola, y luego capturarlo y guardarlo en un archivo. Esa es la imagen mental que tengo de lo que debe estar sucediendo cuando uso cat y redirijo la salida que no puedo ver. Parecía que si hubiera una manera de abrir dos archivos, conectarlos y luego cerrarlos, sería más eficiente que ejecutar todas las líneas de código cat. Gracias por informarme sobre la conexión directa.
cwd
@cwd Sería posible diseñar un sistema de archivos donde pudiera unir dos archivos de esa manera, pero eso complicaría enormemente el diseño del sistema de archivos. Se optimizaría para esa operación a costa de hacer que muchas tareas comunes sean más complicadas y lentas.
Gilles 'SO- deja de ser malvado'
@Gilles: sería interesante saber más sobre los detalles de bajo nivel. Para mí, leer todos los sectores del disco duro para varios archivos y luego volcarlos en otros sectores no utilizados en el disco parece ineficiente. Y creo que los archivos grandes deben almacenarse en múltiples bloques de sectores libres a veces porque puede que no siempre haya suficientes bloques uno al lado del otro para almacenarlos. Por lo tanto, teóricamente, podría unir archivos en uno eliminando el marcador EOF y señalando al grupo de sectores al comienzo del siguiente archivo. * nix es poderoso, así que me preguntaba si había una mejor manera que el gato.
cwd
@cwd No hay un "marcador EOF". Ningún sistema de archivos moderno y sensato funciona así, porque evita que algunos caracteres aparezcan en los archivos (o de lo contrario requiere codificaciones complejas). Pero incluso si hubiera un marcador EOF, la mayoría de las veces, no tendría el archivo correcto después.
Gilles 'SO- deja de ser malvado'
Me refería al concepto del marcador EOF y no a un marcador EOF real. De lo contrario, si observa los bits y bytes de un archivo en el disco duro, ¿cómo sabe dónde termina? ¿Especifica la longitud del archivo al comienzo? Estoy hablando de una cosa de muy bajo nivel. ¿A eso te refieres también?
cwd
3

Una vez tuve exactamente este problema: quería unir algunos archivos, pero no tenía suficiente espacio en disco para mantenerlos doblemente.

Entonces escribí un montón de programas:

  • uno para "absorber" un archivo leyéndolo, enviándolo a stdout y, si ha terminado, eliminándolo
  • y uno para almacenar datos "sobre la marcha".

Esto me permitió hacer algo como

partto sourcefile | mybuffer 128M >>cumufile

y así eliminar el archivo fuente mientras 128M todavía no estaba escrito. Un poco peligroso, pero si los datos no son tan valiosos, o existen en otro lugar, es factible.

Si es necesario, puedo proporcionar la fuente.

glglgl
fuente
0

Técnicamente hablando, esta es una forma de acceder al archivo completo sin tener que leer y escribir todo el contenido, y podría ser útil para archivos grandes o si queda poco espacio:

$ mkfifo myImage.iso
$ cat xa{a..g} > myImage.iso &

Y luego usar myImage.iso, por ejemplo

$ md5sum myImage.iso

Aunque, por supuesto, myImage.isoes un archivo especial (llamado canalización) y no un archivo normal, por lo que puede ser útil o no, dependiendo de lo que intente hacer.

golimar
fuente
0

División de archivos

Dividir por tamaño

Si desea dividir archivos grandes en archivos pequeños y elegir el nombre y el tamaño de los archivos de salida pequeños, esta es la manera.

split -b 500M videos\BigVideoFile.avi SmallFile.

De esta manera, elige dividir un archivo grande en partes más pequeñas de 500 MB. También desea que los nombres de los archivos de piezas sean SmallFile. Tenga en cuenta que necesita un punto después del nombre del archivo. El resultado debería ser la generación de nuevos archivos como este:

SmallFile.ab SmallFile.ad SmallFile.af SmallFile.ah SmallFile.aj
SmallFile.aa SmallFile.ac SmallFile.ae SmallFile.ag SmallFile.ai SmallFile.ak
...

Dividir por número de líneas

De esta manera, dividirá el archivo de texto en archivos más pequeños limitados a 50 líneas.

split -l 50 text_to_split.txt

El resultado debería ser algo como esto:

xaa xab xac ...

Dividir por bytes

Dividir en archivos pequeños con tamaño personalizado de archivos pequeños en bytes:

split -b 2048 BigFile.mp4

El resultado debe ser similar al resultado de la división por número de líneas .

Unir archivos

Puede unir archivos de dos maneras. El primero es:

cat SmallFile.* > OutputBigVideoFile.avi

o con:

cat SmallFile.?? > OutputBigVideoFile.avi

Nota: Cuando unes archivos, los archivos pequeños no deben dañarse. Además, todos los archivos pequeños (partes) deben estar en el mismo directorio.

Nole
fuente