Скажем, у меня есть файл 80 /root/bigfile
ГБ в системе 100 ГБ и я хочу поместить этот файл в архив /root/bigarchive.tar
Очевидно, мне нужно удалить этот файл одновременно с добавлением его в архив. Отсюда мой вопрос:
Как удалить файл одновременно с добавлением в архив?
tar
zip
compression
gzip
user123456
источник
источник
Несжатый архив tar одного файла состоит из заголовка, файла и конечной панели. Итак, ваша принципиальная проблема заключается в том, как добавить 512 байт заголовка в начало вашего файла. Вы можете начать с создания желаемого результата только с заголовком:
Затем скопируйте первые 10G вашего файла. Для простоты мы предполагаем, что ваш dd может читать / записывать 1Gib одновременно:
Теперь мы освободили скопированные данные из исходного файла:
Это заменяет данные разреженными нулями, которые не занимают места в файловой системе. Продолжайте таким образом, добавляя a
skip=10
к следующемуdd
, а затем увеличиваяfallocate
начальное смещение до-o 10GiB
. В самом конце добавьте несколько нулевых символов для дополнения окончательного tar-файла.Если ваша файловая система не поддерживает,
fallocate
вы можете сделать что-то похожее, но начиная с конца файла. Сначала скопируйте последнее 10Gibytes файла в промежуточный файл с именем, скажем,part8
. Затем используйтеtruncate
команду, чтобы уменьшить размер исходного файла. Продолжайте аналогичным образом, пока у вас не будет 8 файлов по 10 ГБ каждый. Вы можете сцепить заголовок иpart1
кbigarchive.tar
, а затем удалитьpart1
, а затем конкатенацияpart2
и удалить его, и так далее.источник
Удаление файла не обязательно делает то, что вы думаете. Вот почему в UNIX-подобных системах системный вызов называется,
unlink
а неdelete
. Со страницы руководства:Как следствие, пока компрессор / архиватор данных читает файл, этот файл остается существующим, занимая место в файловой системе.
источник
Учитывая контекст, я буду интерпретировать этот вопрос как:
Как удалить данные с диска сразу после его чтения, до того, как будет прочитан весь файл, чтобы было достаточно места для преобразованного файла.
Преобразование может быть любым, что вы хотите сделать с данными: сжатие, шифрование и т. Д.
Ответ таков:
Вкратце: прочитайте данные, бросьте их в gzip (или что вы хотите с ними делать), буферизируйте вывод, чтобы мы наверняка прочитали больше, чем записали, и записали его обратно в файл. Это версия, которая красивее и показывает результат при запуске:
Я пройдусь по ней, строка за строкой:
cat "$file"
читает файл, который вы хотите сжать. Это бесполезное использование cat (UUOC), так как следующая часть, pv, также может читать файл, но я считаю, что это красивее.Он передает его по каналу,
pv
который показывает информацию о прогрессе (-cN
говорит, что «используйте какой-то [c] ursor» и дайте ему [N] ame).Те каналы, в
gzip
которые явно выполняется сжатие (чтение из stdin, вывод в stdout).Это трубы в другое
pv
(представление трубы).Это трубы в
dd bs=$buffer iflag=fullblock
.$buffer
Переменный является число, что - то вроде 50 мегабайта. Тем не менее, это много оперативной памяти, которую вы хотите выделить для безопасной обработки вашего файла (в качестве точки данных, буфер объемом 50 МБ для файла объемом 2 ГБ вполне подойдет).iflag=fullblock
Говоритdd
дочитать до$buffer
байт перед тем конвейер через. В начале gzip напишет заголовок, поэтому выходные данные gzip окажутся в этойdd
строке. Затемdd
будет ждать, пока у него не будет достаточно данных, прежде чем передать его, и поэтому ввод может читать дальше. Кроме того, если у вас есть несжимаемые части, выходной файл может быть больше, чем входной файл. Этот буфер гарантирует, что до$buffer
байтов это не проблема.Затем мы переходим в другую строку представления канала и, наконец, в нашу
dd
строку вывода . Эта строка имеетof
(выходной файл) иconv=notrunc
указывает, гдеnotrunc
говоритdd
не обрезать (удалить) выходной файл перед записью. Таким образом, если у вас есть 500 байтовA
и вы пишете 3 байтаB
, файл будетBBBAAAAA...
(вместо того, чтобы быть замененным наBBB
).Я не покрывал
2>/dev/null
части, и они не нужны. Они просто приводят в порядок вывод, подавляя сообщениеdd
«Я закончил и написал это много байтов». Обратная косая черта в конце каждой строки (\
) заставляет bash рассматривать все это как одну большую команду, которая соединяет друг с другом.Вот полный скрипт для более легкого использования. К счастью, я положил его в папку «gz-in-place». Затем я понял аббревиатуру, которую я сделал: GZIP: GNU ZIP на месте. Итак, я представляю, GZIP.sh:
Я чувствую, что добавляю еще одну строку буферизации перед gzip, чтобы предотвратить слишком
dd
длинную запись, когда строка буферизации очищается, но только с буфером 50 МБ и 1900 МБ/dev/urandom
данных, похоже, все равно уже работает (md5sums совпал после распаковки). Достаточно хорошее соотношение для меня.Другим улучшением было бы обнаружение слишком длинного письма, но я не вижу, как это сделать, не удаляя красоту вещи и не создавая много сложности. На этом этапе вы могли бы просто сделать его полноценной программой на Python, которая делает все правильно (с отказоустойчивыми файлами для предотвращения уничтожения данных).
источник