Fondamentalement, ce dont vous avez besoin est la possibilité de canaliser le fichier dans tar et de "loper" le front au fur et à mesure.
Sur StackOverflow, quelqu'un a demandé comment tronquer un fichier à l'avant , mais il semble que ce ne soit pas possible. Vous pouvez toujours remplir le début du fichier avec des zéros d'une manière spéciale afin que le fichier devienne un fichier clairsemé , mais je ne sais pas comment faire. Nous pouvons cependant tronquer la fin du fichier. Mais tar doit lire l'archive en avant, pas en arrière.
Solution 1
Un niveau d'indirection résout chaque problème. Commencez par inverser le fichier sur place, puis lisez-le en arrière (ce qui entraînera la lecture du fichier d'origine vers l'avant) et tronquez la fin du fichier inversé au fur et à mesure.
Vous devrez écrire un programme (c, python, peu importe) pour échanger le début et la fin du fichier, morceau par morceau, puis diriger ces morceaux vers tar tout en tronquant le fichier un morceau à la fois. C'est la base de la solution 2 qui est peut-être plus simple à mettre en œuvre.
Solution 2
Une autre méthode consiste à diviser le fichier en petits morceaux sur place , puis à supprimer ces morceaux à mesure que nous les extrayons. Le code ci-dessous a une taille de bloc d'un mégaoctet, ajustez en fonction de vos besoins. Plus gros est plus rapide mais prendra plus d'espace intermédiaire lors du fractionnement et de l'extraction.
Fractionnez le fichier 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
Canalisez ces fichiers dans tar (notez que nous avons besoin de la variable chunkprefix dans le deuxième 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.
Puisque nous utilisons un tube nommé ( mkfifo fifo
), vous n'avez pas besoin de diriger tous les morceaux à la fois. Cela peut être utile si vous manquez d'espace. Vous pouvez suivre les étapes suivantes:
- Déplacez, par exemple, les derniers morceaux de 10 Go vers un autre disque,
- Commencez l'extraction avec les morceaux que vous avez encore,
- Une fois la
while [ -e … ]; do cat "$chunk…; done
boucle terminée (deuxième terminal):
- N'arrêtez PAS la
tar
commande, ne supprimez PAS le fifo (premier terminal), mais vous pouvez exécuter sync
, au cas où,
- Déplacez certains fichiers extraits dont vous savez qu'ils sont terminés (tar n'est pas bloqué en attendant que les données finissent d'extraire ces fichiers) vers un autre disque,
- Reculez les morceaux restants,
- Reprenez l'extraction en exécutant à
while [ -e … ]; do cat "$chunk…; done
nouveau les lignes.
Bien sûr, tout cela est en haute voltige , vous voudrez d'abord vérifier que tout va bien sur une archive factice, car si vous faites une erreur, alors adieu les données .
Vous ne saurez jamais si le premier terminal ( tar
) a réellement fini de traiter le contenu du fifo, donc si vous préférez, vous pouvez l'exécuter à la place, mais vous n'aurez pas la possibilité d'échanger de manière transparente des morceaux avec un autre disque:
chunkprefix="chunk_"
currentchunk=0
while [ -e "$chunkprefix$currentchunk" ]; do
cat "$chunkprefix$currentchunk" && rm -f "$chunkprefix$currentchunk"
currentchunk=$((currentchunk+1))
done | tar -xf -
Avertissement
Notez que pour que tout cela fonctionne, votre shell, votre queue et votre troncature doivent gérer correctement les entiers 64 bits (vous n'avez pas besoin d'un ordinateur 64 bits ni d'un système d'exploitation pour cela). Le mien le fait, mais si vous exécutez le script ci-dessus sur un système sans ces exigences, vous perdrez toutes les données dans archive.tar .
Et dans tous les cas, quelque chose d'autre ne va pas, vous perdrez toutes les données dans archive.tar de toute façon, alors assurez-vous d'avoir une sauvegarde de vos données.