2008-11-14 13 views
8

Supongamos que tiene dos archivos enormes (varios GB) que desea concatenar juntos, pero que tiene muy poco espacio libre en el disco (digamos un par de cientos de MB). Es decir, dado file1 y file2, desea terminar con un único archivo que es el resultado de concatenar file1 y file2 junto byte por byte, y eliminar los archivos originales.¿Cómo se pueden concatenar dos archivos enormes con muy poco espacio libre en el disco?

No puede hacer lo obvio cat file2 >> file1; rm file2, ya que entre las dos operaciones, se quedaría sin espacio en disco.

Se aceptan soluciones en cualquiera y todas las plataformas con herramientas gratuitas o no gratuitas; este es un problema hipotético que pensé mientras estaba descargando un ISO de Linux el otro día, y la descarga se interrumpió a mitad de camino debido a un problema inalámbrico.

+1

Le recomiendo que revise la firma del archivo después de su finalización. Esto le ahorrará muchos problemas más adelante si cualquiera de las partes se dañó. –

Respuesta

8

Creo que la dificultad está en determinar cómo se puede recuperar el espacio de los archivos originales.

creo que el siguiente podría funcionar:

  1. Asignar un archivo disperso del tamaño combinado .
  2. Copie 100Mb desde el final del segundo archivo hasta el final del nuevo archivo.
  3. Truncar 100 Mb del final del segundo archivo
  4. Loop 2 & 3 hasta que termine el segundo archivo (con 2. modificado al lugar correcto en el archivo de destino).
  5. Do 2 4 pero con el primer archivo.

Todo esto se basa en la compatibilidad de archivos dispersos y el espacio libre de truncamiento de archivos inmediatamente.

Si realmente deseaba hacer esto, debe investigar el comando dd. lo que puede hacer el paso de copia de

Alguien en otra respuesta dio una solución clara y simple que no requiere archivos dispersos, pero no copiar fichero2 dos veces:

  1. trozos Copia 100 Mb desde el final del archivo de 2 a un nuevo archivo 3, terminando en orden inverso. Truncar el archivo 2 sobre la marcha.
  2. Copie trozos de 100Mb desde el final del archivo 3 en el archivo 1, terminando con los trozos en su orden original, al final del archivo 1. Truncar el archivo 3 sobre la marcha.
+0

Podría usar dd para esto. –

+0

Sí, estaba pensando en dd, pero parece una discusión teórica. –

4

Con esas limitaciones, espero que tengas que manipular el sistema de archivos; edite directamente el tamaño del archivo y los bloques de asignación.

En otras palabras, olvídate de mezclar cualquier bloque de contenido de archivo, simplemente edita la información sobre esos archivos.

1

A riesgo de sonar impertinente, ¿ha considerado la opción de obtener un disco más grande? Probablemente sería más rápido ...

+0

Es una pregunta hipotética: en mi caso, (apenas) tenía suficiente espacio libre en el disco para hacer el gato. También se podría utilizar fácilmente medios externos, como una llave USB. –

+0

Sí, aprecio que sea una pregunta hipotética. Solo quería asegurarme de que se representara la solución práctica aburrida, junto con las astutas barajadoras de bytes;) –

+0

Me parece que pensar que siempre hay alguna manera de obtener más espacio molesto. Después de todo, siempre hay alguna manera de obtener archivos más grandes. – Svante

0

dos pensamientos:

Si tiene suficiente memoria RAM física, usted podía leer el segundo archivo completo en la memoria, borrar, después la escribe en modalidad de apertura al primer archivo. Por supuesto, si pierde energía después de eliminar pero antes de completar la escritura, ha perdido parte del segundo archivo para siempre.

Reduzca temporalmente el espacio en disco utilizado por la funcionalidad del sistema operativo (por ejemplo, memoria virtual, "papelera de reciclaje" o similar). Probablemente solo de uso en Windows.

0

Dudo que esta sea una respuesta directa a la pregunta. Puede considerar esto como una forma alternativa de resolver el problema.

Creo que es posible considerar el 2 ° archivo como la parte 2 del primer archivo. Por lo general, en la aplicación zip, vemos que un archivo enorme se divide en varias partes. Si abre la primera parte, la aplicación considerará automáticamente las otras partes en el procesamiento posterior.

Podemos simular lo mismo aquí. Como señaló @edg, el sistema de archivos de retoque sería de una sola manera.

15

tiempo dedicado a encontrar la solución inteligente que implica barajar-sector del disco y la manipulación de la cadena de archivo: 2-4 horas

tiempo dedicado a la adquisición/software de grabación hacer copia en su lugar y truncar: 2-20 horas

veces la mediana tasa programador $ 50/hr: $ 400- $ 1200

coste de 1 TB unidad USB: $ 100- $ 200

capacidad de entender la frase "costo de oportunidad": no tiene precio

+8

conocimiento obtenido del ejercicio teórico: no tiene precio –

+0

@edg: o inútil a menos que pueda aplicarlo para ganar dinero más tarde ;-) –

+0

¡Me he echado a reír! Si bien estoy de acuerdo con el punto, agregaría que, finalmente, el mismo problema se repite. – Josh

1

No es muy eficiente, pero creo que se puede hacer.

Abra el primer archivo en el modo de adición y copie los bloques del segundo archivo hasta que el disco esté casi lleno. Para el resto del segundo archivo, copie los bloques desde el punto donde detuvo el inicio del archivo a través de la E/S de acceso aleatorio. Trunque el archivo después de haber copiado el último bloque. Repita hasta que termine.

1

bien, para el entretenimiento teórico, y sólo si prometes no pierda su tiempo realmente hacerlo:

  • archivos se almacenan en el disco en piezas
  • las piezas están unidas en una cadena de

Así que usted puede concatenar los archivos por:

  • que une la última pieza del primer archivo a la primera pieza del último archivo
  • la alteración de la entrada de directorio para el primer archivo para cambiar la última pieza y tamaño de archivo
  • la eliminación de la entrada de directorio para el último archivo
  • limpieza del primer archivo de fin-de- marcador de archivo, si lo hay
  • , tenga en cuenta que si el último segmento del primer archivo está parcialmente lleno, tendrá que copiar los datos "arriba" de los segmentos del último archivo para evitar tener basura en el medio del archivo [gracias @¡Cuña!]

Esto sería óptimamente eficiente: alteraciones mínimas, copia mínima, no requiere espacio libre en el disco.

ahora ir a comprar una unidad USB ;-)

+0

A menos que el tamaño del primer archivo sea un múltiplo entero del tamaño del clúster, el último clúster estará parcialmente vacío, por lo que el archivo vinculado tendría basura en el medio . No veo ninguna manera de hacer esto en el caso general que evita tener que cambiar los datos en el segundo archivo. – Wedge

+0

@ [Wedge]: buen punto, editado para reflejar –

1

Obviamente, la respuesta económica es comprar más almacenamiento asumiendo que es una respuesta posible. Sin embargo, puede que no sea así: el sistema integrado no tiene forma de conectar más almacenamiento, o incluso no tiene acceso al equipo en sí, es decir, sonda espacial en vuelo.

La respuesta presentada anteriormente basada en el sistema de archivos dispersos es buena (aparte de la naturaleza destructiva si algo sale mal) si tiene un sistema de archivos disperso. ¿Y si no lo haces?

Comenzando desde el final del archivo 2 copie bloques al inicio del archivo de destino revirtiéndolos sobre la marcha. Después de cada bloque, trunca el archivo fuente a la longitud no copiada. Repita para el archivo n. ° 1.

En este punto, el archivo de destino contiene todos los datos hacia atrás, los archivos de origen se han ido.

Lee un bloque de la tarta y del final del archivo de destino, inviértalos y escríbelos en el lugar del que procede el otro. Ábrete camino hacia adentro volteando bloques.

Cuando haya terminado, el archivo de destino es la concatenación de los archivos de origen. No se necesita un sistema de archivos disperso, no hay problemas con el sistema de archivos necesario. Esto se puede llevar a cabo en cero bytes, ya que los datos se pueden guardar en la memoria.

6

Aquí hay una ligera mejora sobre mi first answer.

Si tiene 100 MB libres, copie los últimos 100 MB del segundo archivo y cree un tercer archivo. Trunque el segundo archivo, ahora es 100 MB más pequeño. Repita este proceso hasta que el segundo archivo se haya descompuesto por completo en trozos individuales de 100 MB.

Ahora, cada uno de esos archivos de 100MB se puede anexar al primer archivo, uno a la vez.

0

usted puede hacer esto:

head file2 --bytes=1024 >> file1 && tail --bytes=+1024 file2 >file2 

puede aumentar 1024 de acuerdo con la cantidad de espacio de disco adicional que tiene, a continuación, sólo tiene que repetir esto hasta que todos los bytes han sido movidos.

Esta es probablemente la manera más rápida de hacerlo (en términos de tiempo de desarrollo)

+0

Esto es esencialmente lo mismo que la solución de Dave Costa: el comando tail cargará todos los primeros 1024 bytes de file2 en la memoria y luego clobber file2. Si hay un corte de energía, corre el riesgo de perder una gran cantidad de datos de forma permanente. –

+0

Creo que esto está roto como está escrito. El intérprete de comandos realizará la redirección antes de que 'file2' sea leído por' tail', nuking. – msandiford

0

Usted puede ser capaz de ganar espacio mediante la compresión de todo el sistema de archivos. Creo que NTFS soporta esto, y estoy seguro de que hay sabores de los sistemas de archivos * nix que lo apoyarían. También tendría la ventaja de que después de copiar los archivos, aún le quedaría más espacio en disco que cuando comenzó.

0

OK, cambiando el problema un poco. Lo más probable es que haya otras cosas en el disco que no necesite, pero no sabe qué es ni dónde está. Si pudieras encontrarlo, podrías eliminarlo, y entonces tal vez tendrías suficiente espacio extra.

Para encontrar estos "tumores", ya sean algunos grandes o muchos pequeños, uso un pequeño programa de muestreo. Comenzando desde la parte superior de un directorio (o la raíz) hace dos pases. En el paso 1, recorre el árbol de directorios, sumando los tamaños de todos los archivos para obtener un total de N bytes. En el paso 2, de nuevo recorre el árbol de directorios, simulando que está leyendo cada archivo.Cada vez que pasa N/20 bytes, imprime la ruta del directorio y el nombre del archivo que está "leyendo". Entonces el resultado final es 20 muestras profundas de nombres de ruta distribuidos uniformemente en todos los bytes debajo del directorio.

Luego solo mire esa lista para las cosas que aparecen mucho que no necesita, y váyase.

(. Es el espacio equivalente del método de muestreo que utilizo para la optimización del rendimiento)

2

si el archivo es altamente compresible (. Es decir, registros):

gzip file1 

gzip file2 

zcat file1 file2 | gzip > file3 

rm file1 

rm file2 

gunzip file3 
Cuestiones relacionadas