По сути, вам нужна возможность направить файл в tar и «перебить» фронт по мере продвижения.
На StackOverflow кто-то спрашивал, как обрезать файл спереди , но кажется, что это невозможно. Вы все еще можете заполнить начало файла нулями особым образом, чтобы файл стал разреженным файлом , но я не знаю, как это сделать. Мы можем обрезать конец файла, хотя. Но tar должен читать архив вперед, а не назад.
Решение 1
Уровень косвенности решает все проблемы. Сначала переверните файл на месте, затем прочитайте его назад (что приведет к чтению исходного файла вперед) и обрежьте конец перевернутого файла по мере продвижения.
Вам нужно написать программу (c, python, что угодно), чтобы обмениваться началом и концом файла, порциями и порциями, а затем передавать эти куски в tar при одновременном усечении файла порциями. Это основа для решения 2, которое, возможно, проще реализовать.
Решение 2
Другой способ - разделить файл на небольшие куски , а затем удалить их по мере их извлечения. Приведенный ниже код имеет размер фрагмента в один мегабайт, который можно настроить в зависимости от ваших потребностей. Чем больше, тем быстрее, но займет больше промежуточного пространства при разделении и во время извлечения.
Разделите файл 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
Передайте эти файлы в tar (обратите внимание, нам нужна переменная chunkprefix во втором терминале):
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.
Поскольку мы используем именованный канал ( mkfifo fifo
), вам не нужно передавать все куски сразу. Это может быть полезно, если вы действительно ограничены в пространстве. Вы можете выполнить следующие шаги:
- Переместите, скажем, последние 10Gb куски на другой диск,
- Начните извлечение с кусками, которые у вас еще есть,
- Когда
while [ -e … ]; do cat "$chunk…; done
цикл завершен (второй терминал):
- НЕ останавливайте
tar
команду, НЕ удаляйте fifo (первый терминал), но вы можете запустить sync
, на всякий случай,
- Переместите некоторые извлеченные файлы, которые, как вы знаете, завершены (tar не остановлен в ожидании данных для завершения извлечения этих файлов) на другой диск,
- Переместить оставшиеся куски назад,
- Возобновите извлечение,
while [ -e … ]; do cat "$chunk…; done
снова запустив строки.
Конечно, это все как волатильность , вам нужно сначала проверить, все ли нормально в фиктивном архиве, потому что, если вы допустили ошибку, попрощайтесь с данными .
Вы никогда не узнаете, tar
действительно ли первый терминал ( ) действительно завершил обработку содержимого fifo, поэтому, если вы предпочитаете, вы можете запустить его вместо этого, но у вас не будет возможности беспрепятственно обмениваться фрагментами с другим диском:
chunkprefix="chunk_"
currentchunk=0
while [ -e "$chunkprefix$currentchunk" ]; do
cat "$chunkprefix$currentchunk" && rm -f "$chunkprefix$currentchunk"
currentchunk=$((currentchunk+1))
done | tar -xf -
отказ
Обратите внимание, что для того, чтобы все это работало, ваша оболочка, хвост и усечение должны правильно обрабатывать 64-разрядные целые числа (для этого вам не нужен ни 64-разрядный компьютер, ни операционная система). Мой делает, но если вы запустите вышеупомянутый скрипт в системе без этих требований, вы потеряете все данные в archive.tar .
И в любом случае, если что-то не так, вы все равно потеряете все данные в archive.tar, поэтому убедитесь, что у вас есть резервная копия ваших данных.