Hay 5 archivos enormes (archivo1, archivo2, ... archivo5) de aproximadamente 10G cada uno y un espacio libre extremadamente bajo que queda en el disco y necesito concatenar todos estos archivos en uno. No es necesario conservar los archivos originales, solo el final.
La concatenación habitual va cat
en secuencia para los archivos file2
... file5
:
cat file2 >> file1 ; rm file2
Desafortunadamente, esta forma requiere un espacio libre de al menos 10G que no tengo. ¿Hay alguna manera de concatenar archivos sin copiarlo realmente pero decirle al sistema de archivos de alguna manera que el archivo1 no termina en el archivo original1 y continúa al inicio del archivo2?
PD. el sistema de archivos es ext4 si eso importa.
filesystems
files
prisa
fuente
fuente
nbd-server
.Respuestas:
AFAIK (desafortunadamente) no es posible truncar un archivo desde el principio (esto puede ser cierto para las herramientas estándar pero para el nivel de syscall ver aquí ). Pero al agregar cierta complejidad, puede usar el truncamiento normal (junto con archivos dispersos): puede escribir al final del archivo de destino sin haber escrito todos los datos intermedios.
Supongamos primero que ambos archivos son exactamente 5GiB (5120 MiB) y que desea mover 100 MiB a la vez. Ejecutas un bucle que consiste en
truncar el archivo fuente en un bloque (liberando espacio en disco)
Pero pruébelo primero con archivos de prueba más pequeños, por favor ...
Probablemente los archivos no sean del mismo tamaño ni múltiplos del tamaño del bloque. En ese caso, el cálculo de las compensaciones se vuelve más complicado.
seek_bytes
yskip_bytes
debe usarse entonces.Si es así, pero necesita ayuda para los detalles, pregunte nuevamente.
Advertencia
Dependiendo del
dd
tamaño del bloque, el archivo resultante será una pesadilla de fragmentación.fuente
En lugar de agrupar los archivos en un solo archivo, tal vez simule un solo archivo con una tubería con nombre, si su programa no puede manejar múltiples archivos.
Como sugiere Hauke, losetup / dmsetup también pueden funcionar. Un experimento rápido Creé 'file1..file4' y con un poco de esfuerzo, hice:
Luego, / dev / dm-0 contiene un dispositivo de bloque virtual con su archivo como contenido.
No he probado esto bien.
Otra edición: el tamaño del archivo debe ser divisible de manera uniforme por 512 o perderá algunos datos. Si es así, entonces eres bueno. Veo que también notó eso a continuación.
fuente
dmsetup
de un dispositivo de bloque virtual (que permite operaciones de búsqueda normales pero no se agrega ni se trunca). Si el tamaño del primer archivo no es múltiplo de 512, debe copiar el último sector incompleto y los primeros bytes del segundo archivo (en suma 512) a un tercer archivo. El dispositivo de bucle para el segundo archivo necesitaría--offset
entonces.Tendrá que escribir algo que copie datos en grupos que sean como máximo tan grandes como la cantidad de espacio libre que tenga. Debería funcionar así:
file2
(utilizandopread()
mediante la búsqueda antes de la lectura en la ubicación correcta).file1
.fcntl(F_FREESP)
para desasignar el espacio desdefile2
.fuente
fcntl(F_FREESP)
que libera el espacio asociado con un rango de bytes dado del archivo (lo hace escaso).fcntl
página de manual (2012-04-15).fallocate
llamada al sistema. Las versiones más nuevas de la utilidad Falocateutil-linux
tienen una interfaz para eso.Sé que es más una solución alternativa de lo que pediste, pero resolvería tu problema (y con poca fragmentación o rasguño):
y entonces
o, si crees que la compresión ayudaría:
Entonces (y SOLO entonces), finalmente
fuente