Я пытаюсь сравнить все файлы в двух папках через md5sum в одной команде. Некоторые, как следующие (bash) в Debian:
$ cd ~/FOLDER1
$ md5sum ~/FOLDER2/* | md5sum -c -
Идея заключается в том, что вывод хэшей из первой md5sum будет передан во вторую и использован в качестве входного файла. Однако тестирование этого показывает, что он просто сравнивает каждый файл в FOLDER2 с самим собой и возвращает «OK» для каждого из них. Я думаю, что причина, по которой это не работает, заключается в том, что имена файлов, выводимые из первой md5sum, включают полный путь. Я посмотрел, md5deep
но не нашел ничего, что могло бы мне помочь. Я знаю, что можно сделать md5sum для одной папки, записать результаты в файл, а затем использовать этот файл в качестве входных данных для второй md5sum. Я хотел сделать все это в одной строке через конвейер, а не использовать две команды и записывать файл.
Редактировать: Принятый ответздесь(использование diff
) может сделать то, что я хочу, но я не знаю, diff
(правильно) ли сравниваются двоичные файлы.
Редактировать: Чтобы получить нужный мне вывод с помощью md5sum (который показывает имя файла и «ОК»), я прибегнул к написанию пакетного файла. Выполнить с помощью diffFolders.sh ~/FOLDER1 ~/FOLDER2
.
#!/bin/bash
HERE=$PWD
cd "$1"
md5sum * > /tmp/md5sum.cmp
cd "$2"
md5sum -c /tmp/md5sum.cmp
cd $HERE
Этот скрипт будет сравнивать только те файлы, которые присутствуют в ~/FOLDER
. Если ~/FOLDER2
есть дополнительные файлы, они не будут сравниваться, и вывод не будет указывать на то, что они вообще существуют.
решение1
Вы можете использоватьзамена процессадля передачи вывода 2 md5sum в diff. Diff в этом случае будет в порядке, поскольку вывод md5 представляет собой обычный текст. Что-то вроде:
diff <(md5 ~/FOLDER1/* | awk '{print $4}') <(md5 ~/FOLDER2/* | awk '{print $4}')
Извините, у меня нет Debian, и я не могу проверить это на нем. Вышеизложенное проверено на OS X с md5, который может немного отличаться в плане вывода. На OS X 4-й столбец md5 — это фактическая сумма md5, поэтому я беру только эти столбцы.
Вместо awk вы также можете использовать cut
, но вам может потребоваться изменить разделитель, чтобы получить 4-й столбец (они не разделены табуляцией).
решение2
Из моего файла .bashrc.
очень старые вещи, должно быть возможно написать гораздо больше кода сортировщика. Я так и не собрался его переписать. (как и все остальное, что было предназначено для временного исправления, используемого вечно) Я публикую этот позорный кусок кода, надеюсь, кто-то сможет сделать его лучше и опубликовать результат :-)
Функции :
- Рекрузивный дир поперечный
- проверка md5sum на уникальность/различие
- Перечисляет обновленные файлы с указанием полного пути
Код говорит сам за себя. arg1 — старый каталог, arg2 — новый каталог.
function find-updated-files-between-old-new(){
[ ! -d "$1" ] || [ ! -d "$2" ] && echo "*** Error: The directory is not found." > /dev/stderr && return 1;
( ( cat <(cd "$1";find . -type f -printf "+%p\n") <(cd "$2";find . -type f -printf "-%p\n")
)|sort -k1.2|tee 1>/dev/null >(uniq -us1|awk -v B="$2" 'BEGIN{sub("/$",""B)}/^-/{print B substr($0,3);
}') >(uniq -ds1|awk -vA="$1" -vB="$2" 'BEGIN{B=g(B);A=g(A)}{
C=substr($0,3);if(f(A)!=f(B))print B C;}function g(y){sub("/$","",y);return y}
function f(y,z,e){e="md5sum \""y""C"\"";e|getline z;close(e);return substr(z,1,32)}' )
) | cat
}
Как следует из названия функции
function find-files-name-collision-between-dir1dir2(){
[ ! -d "$1" ] || [ ! -d "$2" ] && echo "*** Error: The directory is not found." > /dev/stderr && return 1;
( cat <(cd "$1";find . -type f -printf "+%p\n") <(cd "$2";find . -type f -printf "-%p\n") )|sort -k 1.2 | uniq -d -s 1
}
Просто для полноты картины
function mv-mergedir1todir2(){
[ ! -d "$1" ] || [ ! -d "$2" ] && echo "*** Error: The directory is not found." && return 1;
( cd "$1" ; tar cf - . ) | (cd "$2" ; tar --keep-old-files xvf - )
echo -e "Done. Duplicate filnames are not replaced. \n#Use \n# ( cd \"$1\" ; tar cf - . ) | (cd \"$2\" ; tar --overwrite xvf - ) \n#if you do not like that. "
}
Этот ужасный кусок кода следует удалить из моего bashrc, однако он существует уже долгое время...
решение3
Довольно долго, но возвращает имя файла и OK, если они совпадают. Вместо использования '-c' он просто сравнивает две строки, выведенные при запуске md5sum для файла в каждой папке.
for f in *; do [[ -f $f ]] && if [ $(md5sum "$f" | cut -d" " -f1) == $(md5sum dir2/"$f" | cut -d" " -f1) ]; then echo "$f" "OK"; else echo "$f" "MODIFIED"; fi; done