Как добавить огромный архив в архив и удалить его параллельно

Скажем, у меня есть файл 80GB /root/bigfile на 100GB-системе и вы хотите поместить этот файл в архив /root/bigarchive.tar

Я, очевидно, должен удалить этот файл одновременно с добавлением его в архив. Отсюда мой вопрос:

Как удалить файл одновременно с добавлением в архив?

  • архивирование файлов без изменений
  • Сценарий Bash для выбора файлов для zip / unzip
  • Как перенаправить unzip -v вывод в файл журнала в сценарии оболочки
  • Почтовый файл имеет разный размер после копирования на флешку
  • Как распаковать несколько каталогов с zip-файлами, которые также содержат подкаталоги с zip-файлами?
  • Подмена текста внутри сжатых файлов
  • Удаленный Unzip через SSH не работает
  • Сжимать zip-файлы с более высоким сжатием
  • 4 Solutions collect form web for “Как добавить огромный архив в архив и удалить его параллельно”

    Если вы используете команду tar GNU, вы можете использовать --remove-files :

    –remove-файлы

    удалять файлы после добавления их в архив

     tar -cvf files.tar --remove-files my_directory 

    Удаление файла не обязательно делает то, что вы думаете. Вот почему в UNIX-подобных системах системный вызов называется unlink а не delete . На странице руководства:

     unlink() deletes a name from the filesystem. If that name was the last link to a file and no processes have the file open, the file is deleted and the space it was using is made available for reuse. If the name was the last link to a file but any processes still have the file open, the file will remain in existence until the last file descriptor referring to it is closed. 

    Как следствие, до тех пор, пока компрессор / архиватор данных читает из файла, этот файл остается в наличии, занимая пространство в файловой системе.

    Несжатый tar-архив одного файла состоит из заголовка, файла и задней панели. Таким образом, ваша основная проблема заключается в том, как добавить 512 байт заголовка в начало вашего файла. Вы можете начать с создания желаемого результата только с заголовком:

     tar cf - bigfile | dd count=1 >bigarchive.tar 

    Затем скопируйте первый 10G вашего файла. Для упрощения мы предполагаем, что ваш dd может читать / писать 1Gib за раз:

     dd count=10 bs=1G if=bigfile >>bigarchive.tar 

    Теперь мы освободим скопированные данные из исходного файла:

     fallocate --punch-hole -o 0 -l 10GiB bigfile 

    Это заменяет данные разреженными нулями, которые не занимают места в файловой системе. Продолжайте таким образом, добавив skip=10 к следующему dd , а затем увеличив начальное смещение -o 10GiB до -o 10GiB . В самом конце добавьте несколько символов nul, чтобы вырезать окончательный файл tar.


    Если ваша файловая система не поддерживает fallocate вы можете сделать что-то подобное, но начиная с конца файла. Сначала скопируйте последние 10Gibytes файла в промежуточный файл, называемый, например, part8 . Затем используйте команду truncate чтобы уменьшить размер исходного файла. Действуйте аналогичным образом, пока у вас не будет 8 файлов из 10Gibyte. Затем вы можете bigarchive.tar заголовок и bigarchive.tar в bigarchive.tar , затем удалить part1 , а затем объединить part2 и удалить его и т. Д.

    Как удалить файл одновременно с добавлением в архив?

    Учитывая контекст, я буду интерпретировать этот вопрос так:

    Как удалить данные с диска сразу после его чтения до того, как будет прочитан полный файл, чтобы было достаточно места для преобразованного файла.

    Преобразование может быть любым, что вы хотите сделать с данными: сжатие, шифрование и т. Д.

    Ответ таков:

     <$file gzip | dd bs=$buffer iflag=fullblock of=$file conv=notrunc 

    Вкратце: прочитайте данные, выбросьте их в gzip (или что бы вы ни делали с ним), буферизируйте вывод, чтобы мы были уверены, что читаем больше, чем пишем, и записываем его обратно в файл. Это более красивая версия и показывает вывод во время работы:

     cat "$file" \ | pv -cN 'bytes read from file' \ | gzip \ | pv -cN 'bytes received from compressor' \ | dd bs=$buffer iflag=fullblock 2>/dev/null \ | pv -cN 'bytes written back to file' \ | dd of="$file" conv=notrunc 2>/dev/null 

    Я пройду через нее:

    cat "$file" читает файл, который вы хотите сжать. Это бесполезное использование cat (UUOC), так как следующая часть, pv, также может читать файл, но я считаю, что это красивее.

    Он -cN его в pv который показывает информацию о ходе ( -cN говорит, что «использует какой-то [c] курсор» и дает ему [N] ame).

    Это касается gzip который, очевидно, делает сжатие (чтение из stdin, выводящее на stdout).

    Это труба в другой pv (вид трубы).

    Это dd bs=$buffer iflag=fullblock в dd bs=$buffer iflag=fullblock . Переменная $buffer – это число, например 50 мегабайт. Однако, как много оперативной памяти, которую вы хотите посвятить безопасному обращению с вашим файлом (в качестве точки данных, 50 МБ-буфер для файла 2 ГБ был в порядке). iflag=fullblock сообщает dd читать до байтов $buffer перед тем, как проложить его. Вначале gzip будет писать заголовок, поэтому вывод gzip появится в этой строке dd . Затем dd будет ждать, пока у него не будет достаточно данных, прежде чем прокладывать его, и поэтому вход может читать дальше. Кроме того, если у вас есть несжимаемые части, выходной файл может быть больше входного файла. Этот буфер гарантирует, что до байтов $buffer это не проблема.

    Затем мы переходим в другую линию просмотра труб и, наконец, на нашу выходную линию dd . Эта строка имеет (выходной файл) и conv=notrunc указан, где notrunc сообщает dd не усекать (удалять) выходной файл перед записью. Поэтому, если у вас есть 500 байт A и вы пишете 3 байта B , файл будет BBBAAAAA... (вместо замены BBB ).

    Я не рассматривал части 2>/dev/null , и они не нужны. Они просто немного убирают выход, подавляя сообщение dd 's «Я закончил и написал это много байтов». Обратные косые черты в конце каждой строки ( \ ) делают bash рассматривать все это как одну большую команду, которая соединяется друг с другом.


    Вот полный сценарий для более простого использования. Я, естественно, помещаю его в папку «gz-in-place». Затем я понял акроним, который я сделал: GZIP: gnu zip на месте. Итак, настоящим, GZIP.sh:

     #!/usr/bin/env bash ### Settings # Buffer is how many bytes to buffer before writing back to the original file. # It is meant to prevent the gzip header from overwriting data, and in case # there are parts that are uncompressible where the compressor might exceed # the original filesize. In these cases, the buffer will help prevent damage. buffer=$((1024*1024*50)) # 50 MiB # You will need something that can work in stream mode from stdin to stdout. compressor="gzip" # For gzip, you might want to pass -9 for better compression. The default is # (typically?) 6. compressorargs="" ### End of settings # FYI I'm aware of the UUOC but it's prettier this way if [ $# -ne 1 ] || [ "x$1" == "xh" ] || [ "x$1" == "x--help" ]; then cat << EOF Usage: $0 filename Where 'filename' is the file to compress in-place. NO GUARANTEES ARE GIVEN THAT THIS WILL WORK! Only operate on data that you have backups of. (But you always back up important data anyway, right?) See the source for more settings, such as buffer size (more is safer) and compression level. The only non-standard dependency is pv, though you could take it out with no adverse effects, other than having no info about progress. EOF exit 1; fi; b=$(($buffer/1024/1024)); echo "Progressing '$1' with ${b}MiB buffer..."; echo "Note: I have no means of detecting this, but if you see the 'bytes read from"; echo "file' exceed 'bytes written back to file', your file is now garbage."; echo ""; cat "$1" \ | pv -cN 'bytes read from file' \ | $compressor $compressorargs \ | pv -cN 'bytes received from compressor' \ | dd bs=$buffer iflag=fullblock 2>/dev/null \ | pv -cN 'bytes written back to file' \ | dd of="$1" conv=notrunc 2>/dev/null echo "Done!"; 

    Я чувствую, что добавляю еще одну строку буферизации перед gzip, чтобы она не писала слишком далеко, когда буферизующая строка dd сбрасывается, но только с буфером 50 Мбайт и 1900 МБ данных /dev/urandom , похоже, все равно работает (md5sums сопоставлены после распаковка). Достаточно хорошее соотношение для меня.

    Еще одним улучшением будет обнаружение записи слишком далеко, но я не вижу, как это сделать, не снимая красоту вещи и не создавая много сложностей. В этот момент вы можете просто сделать его полноценной программой python, которая сделает все правильно (с отказами для предотвращения уничтожения данных).

    Interesting Posts

    Как я могу сменить разные файлы на псевдоним, который изменяется

    В чем разница между \ b и \ <в команде grep

    Что такое ядро, «инструменты и утилиты GNU», оболочка и диспетчер окон?

    Устранение недостающих зависимостей пакета при попытке установить октаву

    Переименуйте все файлы в папке, чтобы удалить текст между двумя одинаковыми символами

    Почему echo $$, echo $ (echo $$) и (echo $$) показывают один и тот же PID?

    Принудительные начальные нули в эхо базовой конверсии

    Менеджер пакетов для AIX

    Создать каталог для каждой строки в данном текстовом файле?

    Является ли это подходящей установкой для отслеживания владения файлами с использованием доли Samba и управления правами?

    Есть ли способ сортировать grep-вывод csv-файла?

    Как назначить задания на Arch Linux?

    Что вдруг заставит программы читать /etc/ld.so.preload при запуске?

    Как установить dig на CentOS 6?

    Как предотвратить экранирование экрана GNU при завершении работы экрана?

    Linux и Unix - лучшая ОС в мире.