Básicamente, lo que necesita es la posibilidad de canalizar el archivo en alquitrán y "cortar" el frente a medida que avanza.
En StackOverflow, alguien preguntó cómo truncar un archivo al frente , pero parece que no es posible. Todavía puede completar el comienzo del archivo con ceros de una manera especial para que el archivo se convierta en un archivo disperso , pero no sé cómo hacerlo. Sin embargo, podemos truncar el final del archivo. Pero tar necesita leer el archivo hacia adelante, no hacia atrás.
Solución 1
Un nivel de indirección resuelve todos los problemas. Primero invierta el archivo en su lugar, luego léalo hacia atrás (lo que resultará en la lectura del archivo original hacia adelante) y trunca el final del archivo invertido a medida que avanza.
Tendrá que escribir un programa (c, python, lo que sea) para intercambiar el principio y el final del archivo, fragmento por fragmento, y luego canalizar estos fragmentos al alquitrán mientras trunca el archivo un fragmento a la vez. Esta es la base para la solución 2, que es quizás más simple de implementar.
Solución 2
Otro método es dividir el archivo en pequeños fragmentos en el lugar , luego eliminar esos fragmentos a medida que los extraemos. El siguiente código tiene un tamaño de fragmento de un megabyte, ajústelo según sus necesidades. Más grande es más rápido, pero ocupará más espacio intermedio al dividir y durante la extracción.
Dividir el archivo archive.tar:
archive="archive.tar"
chunkprefix="chunk_"
# 1-Mb chunks :
chunksize=1048576
totalsize=$(wc -c "$archive" | cut -d ' ' -f 1)
currentchunk=$(((totalsize-1)/chunksize))
while [ $currentchunk -ge 0 ]; do
# Print current chunk number, so we know it is still running.
echo -n "$currentchunk "
offset=$((currentchunk*chunksize))
# Copy end of $archive to new file
tail -c +$((offset+1)) "$archive" > "$chunkprefix$currentchunk"
# Chop end of $archive
truncate -s $offset "$archive"
currentchunk=$((currentchunk-1))
done
Canalice esos archivos en tar (tenga en cuenta que necesitamos la variable chunkprefix en el segundo terminal):
mkfifo fifo
# In one terminal :
(while true; do cat fifo; done) | tar -xf -
# In another terminal :
chunkprefix="chunk_"
currentchunk=0
while [ -e "$chunkprefix$currentchunk" ]; do
cat "$chunkprefix$currentchunk" && rm -f "$chunkprefix$currentchunk"
currentchunk=$((currentchunk+1))
done > fifo
# When second terminal has finished :
# flush caches to disk :
sync
# wait 5 minutes so we're sure tar has consumed everything from the fifo.
sleep 300
rm fifo
# And kill (ctrl-C) the tar command in the other terminal.
Como usamos una tubería con nombre (mkfifo fifo
), no es necesario que canalice todos los fragmentos a la vez. Esto puede ser útil si tienes poco espacio. Puedes seguir los siguientes pasos:
- Muévase, digamos los últimos fragmentos de 10 Gb a otro disco,
- Comienza la extracción con los trozos que aún tienes,
- Cuando el
while [ -e … ]; do cat "$chunk…; done
ciclo ha terminado (segundo terminal):
- NO detenga el
tar
comando, NO quite el fifo (primer terminal), pero puede ejecutarsync
, por si acaso,
- Mueva algunos archivos extraídos que sabe que están completos (el tar no se detiene esperando que los datos terminen de extraer estos archivos) a otro disco,
- Mueve los trozos restantes hacia atrás,
- Reanude la extracción ejecutando las
while [ -e … ]; do cat "$chunk…; done
líneas nuevamente.
Por supuesto, todo esto es de alto voltaje , primero querrá verificar que todo esté bien en un archivo ficticio, porque si comete un error, adiós a los datos .
Nunca sabrá si el primer terminal ( tar
) realmente ha terminado de procesar el contenido del fifo, por lo que si lo prefiere, puede ejecutar esto, pero no tendrá la posibilidad de intercambiar fragmentos sin problemas con otro disco:
chunkprefix="chunk_"
currentchunk=0
while [ -e "$chunkprefix$currentchunk" ]; do
cat "$chunkprefix$currentchunk" && rm -f "$chunkprefix$currentchunk"
currentchunk=$((currentchunk+1))
done | tar -xf -
Descargo de responsabilidad
Tenga en cuenta que para que todo esto funcione, su shell, cola y truncamiento deben manejar enteros de 64 bits correctamente (no necesita una computadora de 64 bits ni un sistema operativo para eso). El mío sí, pero si ejecuta el script anterior en un sistema sin estos requisitos, perderá todos los datos en archive.tar .
Y en cualquier caso, algo diferente a eso va mal, perderá todos los datos en archive.tar de todos modos, así que asegúrese de tener una copia de seguridad de sus datos.