2016-04-28 13 views
7

У меня есть каталог со структурой, например, так:md5 всех файлов в дереве каталогов

. 
├── Test.txt 
├── Test1 
│   ├── Test1.txt 
│   ├── Test1_copy.txt 
│   └── Test1a 
│    ├── Test1a.txt 
│    └── Test1a_copy.txt 
└── Test2 
    ├── Test2.txt 
    ├── Test2_copy.txt 
    └── Test2a 
     ├── Test2a.txt 
     └── Test2a_copy.txt 

Я хотел бы создать Баш скрипт, который делает md5 контрольной сумму каждый файл в этом каталоге. Я хочу, чтобы иметь возможность вводить имя сценария в CLI, а затем путь к каталогу, который я хочу использовать, и заставить его работать. Я уверен, что есть много способов сделать это. В настоящее время у меня есть:

#!/bin/bash 

for file in "$1" ; do 
    md5 >> "${1}__checksums.md5" 
done 

Это просто зависает и не работает. Возможно, я должен использовать находку?

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

ответ

3

Как насчет:

find /path/you/need -type f -exec md5sum {} \; > checksums.md5

Update # 1: Улучшена команда, основанную на @ twalberg-х рекомендации для обработки пробелов в именах файлов.

Update # 2: Усовершенствованные на основе @ Jil-х внушения, чтобы удалить ненужные xargs вызов и использовать -exec возможность найти вместо этого.

Update # 3: @Blake наивной реализации вашего сценария будет выглядеть примерно так:

#!/bin/bash 
# Usage: checksumchecker.sh <path> 
find "$1" -type f -exec md5sum {} \; > "$1"__checksums.md5 
+0

Я бы порекомендовал 'find/path-type f -print0 | xargs -0 md5sum', чтобы иметь дело с именами файлов, которые в противном случае могли бы быть непреднамеренно разделены из-за пробелов ... – twalberg

+0

@twalberg Хорошая точка, спасибо! Я обновляю ответ. – taskalman

+0

Спасибо @taskalman. «Вы можете создать путь и вывести имя файла из $ 1, если мы поместим его в ваш скрипт. Обратите внимание, что вам придется обрабатывать косые черты в вашем параметре пути, чтобы сделать его частью имени файла в вашем скрипте». Не могли бы вы объяснить это немного дальше? Я не совсем понимаю, что вы имеете в виду. – Bleakley

1
#!/bin/bash 
shopt -s globstar 
md5sum "$1"/** > "${1}__checksums.md5" 

Объяснение: shopt -s globstar(manual) позволяет ** рекурсивный Глоб подстановочные. Это будет означать, что "$1"/** будет расширяться до списка всех файлов, рекурсивно расположенных в каталоге, заданном как параметр $1. Затем скрипт просто вызывает md5sum с этим файлом в качестве параметра, а > "${1}__checksums.md5" перенаправляет вывод в файл.

+1

Ваш ответ может быть правильным, но было бы намного полезнее, если бы вы может объяснить, что он делает или как это работает – kommradHomer

+1

@jil да, не могли бы вы объяснить, как это работает? Я думаю, это может быть то, что я ищу. – Bleakley

+0

@Blake Имейте в виду, что это не будет содержать скрытые файлы. Если вы хотите, чтобы скрытые файлы не игнорировались, активируйте опцию «dotglob»: 'shopt -s dotglob' [[source] (https://www.gnu.org/software/bash/manual/html_node/The-Shopt- Builtin.html # The-Shopt-Builtin)]. – TeWu

16

Использование md5deep

md5deep -r path/to/dir > sums.md5 

Использование find и md5sum

find relative/path/to/dir -type f -exec md5sum {} + > sums.md5 

Имейте в виду, что при запуске проверки на ваших MD5 сумм с md5sum -c sums.md5, вам нужно запустить его из того же каталога, из которого вы создали файл sums.md5. Это связано с тем, что find выводит пути, относящиеся к вашему текущему местоположению, которые затем помещаются в файл sums.md5.

Если это проблема, вы можете сделать абсолютное значение relative/path/to/dir (например, положив $PWD/ перед вашей дорогой). Таким образом, вы можете запустить проверку на sums.md5 из любого места. Недостатком является то, что теперь sums.md5 содержит абсолютные пути, что делает его больше.

Полнофункциональный функция с помощью find и md5sum

Вы можете поместить эту функцию в файл .bashrc (находится в вашем $HOME каталоге):

function md5sums { 
    if [ "$#" -lt 1 ]; then 
    echo -e "At least one parameter is expected\n" \ 
      "Usage: md5sums [OPTIONS] dir" 
    else 
    local OUTPUT="checksums.md5" 
    local CHECK=false 
    local MD5SUM_OPTIONS="" 

    while [[ $# > 1 ]]; do 
     local key="$1" 
     case $key in 
     -c|--check) 
      CHECK=true 
      ;; 
     -o|--output) 
      OUTPUT=$2 
      shift 
      ;; 
     *) 
      MD5SUM_OPTIONS="$MD5SUM_OPTIONS $1" 
      ;; 
     esac 
     shift 
    done 
    local DIR=$1 

    if [ -d "$DIR" ]; then # if $DIR directory exists 
     cd $DIR # change to $DIR directory 
     if [ "$CHECK" = true ]; then # if -c or --check option specified 
     md5sum --check $MD5SUM_OPTIONS $OUTPUT # check MD5 sums in $OUTPUT file 
     else       # else 
     find . -type f ! -name "$OUTPUT" -exec md5sum $MD5SUM_OPTIONS {} + > $OUTPUT # Calculate MD5 sums for files in current directory and subdirectories excluding $OUTPUT file and save result in $OUTPUT file 
     fi 
     cd - > /dev/null # change to previous directory 
    else 
     cd $DIR # if $DIR doesn't exists, change to it to generate localized error message 
    fi 
    fi 
} 

После запуска source ~/.bashrc, вы можете использовать md5sums как нормальный команда:

md5sums path/to/dir 

будет генерировать checksums.md5 файл в каталоге path/to/dir, содержащий MD5 суммы всех файлов в этой директории и подкаталогах. Использование:

md5sums -c path/to/dir 

проверить суммы из path/to/dir/checksums.md5 файла.

Отметьте, что path/to/dir может быть относительным или абсолютным, md5sums будет работать в любом случае. Результат checksums.md5 Файл всегда содержит пути относительно path/to/dir. Вы можете использовать другое имя файла, а затем по умолчанию checksums.md5, предоставив -o или --output. Все варианты, кроме -c, --check, -o и --output переданы md5sum.

Первая часть определения md5sums отвечает за варианты синтаксического анализа. См. this answer для получения дополнительной информации. Вторая половина содержит пояснительные комментарии.

+0

** Примечание: ** По моему опыту использования команды '-exec {} +' вариант 'exec' заставляет его работать быстрее, чем когда вариант '-exec command;' используется. – TeWu

+0

Спасибо! Я очень благодарен за то, что этот сложный (для меня!) Сценарий закомментирован. – Bleakley

+0

@TeWu 'md5deep' не работает в' Ubuntu 16.04' –

1

Обновлено Ответ

Если вам нравится ответ ниже, или любой из других, вы можете сделать функцию, которая делает команду для вас. Таким образом, чтобы проверить его, введите следующую команду в терминале, чтобы объявить функцию:

function sumthem(){ find "$1" -type f -print0 | parallel -0 -X md5 > checksums.md5; } 

Тогда вы можете просто использовать:

sumthem /Users/somebody/somewhere 

Если это работает, как вы хотите, вы можете добавить эту строку в конец вашего «Баш профиль» и функция будет объявлена ​​и доступна, когда вы вошли в систему. Ваш «Баш профиль», вероятно, в $HOME/.profile

Оригинальный ответ

Почему бы не получить все ваши ядра процессора, работающие параллельно для вас?

find . -type f -print0 | parallel -0 -X md5sum 

Это находит все файлы (-type f) в текущем каталоге (.) и выводит их с нулевым байтом в конце. Затем они передаются в GNU Parallel, в котором говорится, что имена файлов заканчиваются нулевым байтом (-0) и что он должен делать как можно больше файлов за один раз (-X), чтобы сохранить создание нового процесса для каждого файла и он должен md5sum файлы.

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

+0

Да, это сработает, но мне придется постоянно перегруппировать всю команду. Я хочу сценарий, где хэширование каталога - это переменная, и имя файла выводится на основе этой переменной. Я не хочу каждый раз набирать команду find - просто имя скрипта, скажем, «makechecksum», и отбрасывать каталог, который будет хэширован в CLI. – Bleakley

+0

Спасибо! очень полезно. – Bleakley

1
md5deep -r $your_directory | awk {'print $1'} | sort | md5sum | awk {'print $1'} 
+1

Измените свой ответ, чтобы включить какое-то объяснение. Кодовые ответы очень мало для обучения будущих читателей SO. Ваш ответ находится в очереди модерации за то, что он некачественный. – mickmackusa

+0

@ AlexJurado-Bitendian вы проверили ответ: 'md5deep' не работает в' ubuntu 16.04' –

+0

Я предполагаю, что Kasun ссылается на https://github.com/jessek/hashdeep/issues/365 –