По сути, вам нужна возможность направить файл в 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, поэтому убедитесь, что у вас есть резервная копия ваших данных.