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

#bash #gzip

#bash #gzip

Вопрос:

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

Но текстовые файлы ежедневно передаются на ПК для резервного копирования, где они сжимаются с помощью gzip , даже до того, как они закончат расти.

Это означает, что у меня часто есть и то, и другое, file.txt и сжатая форма file.txt.gz , где несжатый файл может быть более актуальным, чем сжатая версия.

Я решаю, какой сохранить, с помощью следующего bash скрипта gzandrm :

 #!/usr/bin/bash

# Given an uncompressed file, look in the same directory for 
# a gzipped version of the file and delete the uncompressed 
# file if zdiff reveals they're identical. Otherwise, the 
# file can be compressed.

# eg:  find . -name '*.txt' -exec gzandrm {} ;

if [[ -e $1 amp;amp; -e $1.gz ]] 
then

    # simple check: use zdiff and count the characters
    DIFFS=$(zdiff "$1" "$1.gz" | wc -c)

    if [[ $DIFFS -eq 0 ]] 
    then

        # difference is '0', delete the uncompressed file
        echo "'$1' already gzipped, so removed"
        rm "$1"

    else

        # difference is non-zero, check manually
        echo "'$1' and '$1.gz' are different"

    fi

else
    # go ahead and compress the file
    echo "'$1' not yet gzipped, doing it now"
    gzip "$1"
fi
  

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

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

Комментарии:

1. Затраты на распаковку для сравнения примерно такие же, как и на повторное сжатие. Почему бы просто не сжать текстовую версию, если она существует, а затем постоянно удалять оригинал в пользу сжатой версии?

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

3. Если это новый файл, разве у него не должно быть нового имени? Не могли бы некоторые файлы на самом деле стать меньше?

4. Имя файла исправлено, поскольку оно определяет содержимое. Иногда операторам оборудования приходится повторять тесты с тем же именем, а иногда удалять файлы, чтобы сэкономить место на диске.

Ответ №1:

Не совсем ясно, какова цель, но, похоже, это простая эффективность, поэтому я думаю, вам следует внести два изменения: 1) проверьте время модификации, как вы предлагаете, и не утруждайте себя сравнением содержимого, если несжатый файл не новее сжатого файла, и 2) используйте zcmp вместо zdiff .

Сначала # 2, ваш скрипт делает это:

 DIFFS=$(zdiff "$1" "$1.gz" | wc -c)
if [[ $DIFFS -eq 0 ]]
  

который выполнит полное различие потенциально больших файлов, подсчитает символы в выходных данных diff и проверит количество. Но все, что вы действительно хотите знать, это отличается ли содержимое. cmp для этого лучше, поскольку он будет сканировать байт за байтом и останавливаться, если обнаружит разницу. На форматирование хорошего текстового сравнения не требуется времени (которое вы в основном проигнорируете); его статус завершения сообщает вам результат. zcmp не так эффективен, как raw cmp , поскольку сначала потребуется выполнить распаковку, но zdiff имеет ту же проблему.

Таким образом, вы могли бы переключиться на zcmp (и исключить использование подоболочки, исключить wc , не вызывать [[ и избежать помещения потенциально больших текстовых данных различий в переменную), просто изменив две вышеуказанные строки на это:

 if zcmp -s "$1"    # if $1 and $1.gz are the same
  

Чтобы сделать еще один шаг и сначала проверить время внесения изменений, вы можете использовать -nt (новее) параметр test команды (также известный как квадратные скобки), переписав приведенную выше строку следующим образом:

 if [ ! "$1" -nt "$1.gz" ] || zcmp -s "$1"
  

в котором говорится, что если несжатая версия не новее сжатой версии ИЛИ если они имеют одинаковое содержимое, то 1 доллар уже загружен, и вы можете удалить его. Обратите внимание, что если несжатый файл не новее, zcmp он вообще не будет запускаться, экономя несколько циклов.

Остальная часть вашего скрипта должна работать как есть.

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

Комментарии:

1. Спасибо @Rob, это дает мне много возможностей попробовать. Я использую FTP для передачи файлов, поэтому время модификации не меняется, и сравнение остается допустимым.

Ответ №2:

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

 if [ $(stat -c %Z $1) -eq ($stat -c %Z $1.gz) ]; then
    echo "Last changed time of $1 is the same as $1.gz"
fi
  

Комментарии:

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

2. Ваш вариант использования дурацкий (повторное использование имен файлов примеров для разных наборов данных?), Но если вы объедините эти тесты, обязательно сэкономьте время вычислений, сначала запустив тест по времени и проверив размер, только если они разные.

3. Отличная идея о том, чтобы сначала проверить время, но реалии производства означают, что иногда нам просто приходится начинать генерировать данные с тем же именем файла заново. Более поздний набор данных заменяет первый (ошибочный) набор данных.

4. Если более поздний набор данных заменяет более ранний набор данных, даже если он меньше, зачем вам вообще сравнивать размер? Если несжатая временная метка новее сжатой (используется -gt в тесте выше), то ее необходимо повторно сжать.

5. Более поздний набор данных может начинаться с малого, но со временем увеличиваться. Но да, новые данные обычно достигают размера старых данных и могут превзойти их, если это не прекратится, потому что это частичное повторное тестирование (в этом случае нам нужно сохранить старые и новые данные). Я думаю, мне следует придерживаться мнения, что я не могу гарантировать сохранение всех данных — некоторые старые данные могут быть удалены.