Как обнаружить только разные файлы в моем сценарии оболочки bash? - PullRequest
0 голосов
/ 30 ноября 2018

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

while IFS= read -r filename;
  do
    # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
    # inspecting the digest of each file individually         #
    # shows many files are identical and so are the digests   #
    # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
    md5 old/$filename; # a456cca87913a4788d980ba4c2f254be
    md5 new/$filename; # a456cca87913a4788d980ba4c2f254be
    # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
    # the below conditional is only supposed to echo "differs"    #
    # if the two digests are different                            #
    # but, instead, it echoes "differs" on every file comparison  #
    # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
    [[ $(md5 old/$filename) = $(md5 new/$filename) ]] || echo differs; # differs
  done < files-to-compare.txt

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

Редактировать

Кроме того, обратите внимание, что использование == вместо =, как в

$(md5 old/$filename) == $(md5 new/$filename) ]] || echo differs; 

, приводит к точно таким же ошибочным выводам.

Edit2

Комментарий предлагает использовать кавычки.Это также не работает.

"$(md5 old/$filename)" == "$(md5 new/$filename)" ]] || echo differs; 

Ответы [ 4 ]

0 голосов
/ 30 ноября 2018

в моем Linux Ubuntu есть команда md5sum: она печатает дайджест и имя файла:

md5sum myFile
215e0f7b4ea9fd9ea5f31106155839fe  myFile

Я имею в виду, что вам нужно извлечь только вывод из вывода:

md5sum myFile | sed 's/^\([^[:blank:]]*\).*$/\1/g'
215e0f7b4ea9fd9ea5f31106155839fe

Затем используйте эту последнюю командную строку в тесте:

...
[[ $(md5sum old/"${filename}" | sed 's/^\([^[:blank:]]*\).*$/\1/g') = $(md5sum new/"${filename}" | sed 's/^\([^[:blank:]]*\).*$/\1/g') ]] || echo differs;
...
0 голосов
/ 30 ноября 2018

Вместо вычисления контрольных сумм MD5 вы можете использовать команду diff, которая сравнивает содержимое файла.Его основное назначение - построчно обрабатывать файлы и сравнивать их различия (и генерировать исправления), но его также легко можно использовать для этой цели.Он возвращает выходное значение 0, если между двумя файлами нет различий, и 1, если есть какие-либо различия.

while IFS= read -r filename;
  do
    if ! diff "old/$filename" "new/$filename" > /dev/null;
    then
      echo "“$filename” differs"
    fi
  done < files-to-compare.txt

Если вы используете GNU diff, вы можете просто использоватьего опция -q, --brief, которая сообщает только о том, что файлы различаются (вместо того, чтобы детализировать, как они различаются):

while IFS= read -r filename;
  do
    diff -q "old/$filename" "new/$filename"
  done < files-to-compare.txt
0 голосов
/ 30 ноября 2018

Вот ваш сценарий исправлен:

while IFS= read -r filename;
    do
        # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
        # inspecting the digest of each file individually         #
        # shows many files are identical and so are the digests   #
        # It also prints MD5 (full file path) = md5_signature!    #
        # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
        md5 "old/$filename"              # please use double quotes
        md5 "new/$filename" 
        # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
        # Using -q eliminates all output from md5 except the sig      #
        # Your script now works correctly                             #
        # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

        [[ $(md5 -q "old/$filename") == $(md5 -q "new/$filename") ]] || echo differs; # differs
    done < files.txt

Проблемы:

  1. У вас была опечатка new/$fullfile вместо new/$filename
  2. Вы должныиспользуйте "new/$filename" (т. е. используйте двойные кавычки) вокруг расширений имен файлов
  3. Используйте md5 -q для сравнения вывода md5 в разных файлах.В противном случае md5 по умолчанию печатает путь к входному файлу в виде MD5 (full_path/base_name) = 2504fcc0c0a57d14aa6b4193b5efaf94.Так как эти пути гарантированно будут разными в двух разных каталогах, разные имена путей приведут к ошибке сравнения строк.

В комментариях выше предполагается, что вы используете md5 в BSDили, скорее всего, на macOS.

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

$ md5 <new/file.pdf
2504fcc0c0a57d14aa6b4193b5efaf94

против, если вы используете имя файла, путь печатается и печатается используемая хеш-подпись MD5:

$ md5 new/file.pdf
MD5 (new/file.pdf) = 2504fcc0c0a57d14aa6b4193b5efaf94

То же самое относится к md5sum в основных утилитах Linux или GNU.

0 голосов
/ 30 ноября 2018

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

grep -v -F -x -f filename1 filename2

Также для этой цели можно использовать только comm для печатиразница между двумя файлами.

comm -13 <(sort filename1) <(sort filename2)

...