3

Я хочу выполнить серию повторных сжатий сжатых файлов, чтобы изучить их свойства.

Сначала я попытался просто сжать файлы .zip в цикле:

for f in $(seq 1 100)
do 
  zip $f.zip -9 -v $(($f-1)).zip
done

Начиная с фиксированного файла 0.zip , я заметил, что, если я перезапущу эти строки, все файлы, кроме первых нескольких, будут иметь разные размеры. После некоторого исследования я понял, что это было вызвано метками времени сжатых файлов. Затем я сбрасываю метки времени перед повторным сжатием:

for f in $(seq 1 100)
do
  touch $(($f-1)).zip -t 200101010101
  zip $f.zip -9 -v $(($f-1)).zip
done

И на этот раз я получил детерминированные результаты для сжатия с использованием zip . Однако использование tar с алгоритмом gzip прежнему не работает. Каждый раз, когда я бегу:

for f in $(seq 1 100)
do
  touch $(($f-1)).tar.gz -t 200101010101
  tar cvfz $f.tar.gz $(($f-1)).tar.gz
done

Я получаю файлы разных размеров, от 4.tar.gz до 100.tar.gz Почему это происходит, и что я могу сделать, чтобы предотвратить это?

3 ответа3

3

Итак, я думаю, что я наконец нашел способ получить вещи, которые я хотел, и это включает использование tar и gzip отдельно (я использую оба инструмента GNU, tar 1.26 и gzip 1.6).

При использовании опции z в tar сначала создается файл tar, а затем сразу же после этого используется эта временная метка для создания файла gzip. Другими словами, я не могу контролировать временную метку промежуточного файла (я не нашел никаких вариантов для этого, кроме изменения mtime исходных файлов, которые архивируются), поэтому файл .tar.gz в конечном итоге не детерминированный.

Однако если я сначала использую tar без gzip, затем изменю метку времени файла tar (например, с помощью touch ), а затем скомпилирую его с помощью gzip, я получу детерминированные результаты.

Кстати, результирующие файлы, использующие двухэтапный процесс, намного меньше (в моем примере ~ 400 КБ вместо ~ 1,2 МБ, которые я получаю при использовании tar с опцией z). Это должно быть связано с настройками по умолчанию при использовании только tar+gzip и gzip. Так как мой оригинальный файл в любом случае был пуст, я не уверен, что уменьшение размера имеет смысл.

В любом случае, краткий ответ на мой вопрос будет:

  • Можно получить детерминированные результаты, но используя tar и gzip отдельно;

  • Кажется невозможным получить детерминированные результаты при использовании tar -z из-за временной метки промежуточного файла tar перед сжатием gzip. Эта временная метка не находится под контролем пользователя.

3

Чтобы включить использование tar для инкрементных резервных копий, некоторые версии tar хранят время, когда файл добавляется в архив. Это может привести к разным выводам при каждом запуске теста и, следовательно, к результатам, которые кажутся недетерминированными.

1

Как вы упомянули, вам нужно будет выполнять шаги tar и gzip отдельно, однако вам не нужен промежуточный файл, вы можете просто передать входные данные из tar в gzip и указать опцию -n в gzip. С man-страницы: эта опция останавливает сохранение имени файла и метки времени в выходном файле.

tar cvf - /path/to/files | gzip -n > archive.tar.gz

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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .