рекурсивный diff очень медленный - проверка содержимого каталогов

Я запускаю diff в двух каталогах, рекурсивно, с несколькими вариантами. Каталоги несколько велики, однако я пытаюсь просто увидеть различия в содержимом папок, а не между файлами, используя параметр -q (я правильно это использую?)

Я также пробовал пробный запуск rsync, который, кажется, занимает столько же времени. Вывод идет через sed, я пробовал без него, похоже, это ни на что не влияет. Я также игнорирую скрытые файлы. Я думаю, что могу неправильно использовать diff -q, чтобы просто сравнить содержимое двух каталогов.

Я использовал блок кода из другого совета, чтобы узнать, сколько времени заняло простое сравнение ОДНОГО из этих каталогов (1 каталог, 14 подкаталогов), и это заняло 88 минут. Тем не менее, каждый файл представлял собой 30-минутное телешоу, поэтому, если diff сравнивает эти файлы, это имеет смысл, но я думал, что -q заставит этого не происходить?

Кроме того, один каталог монтируется через AFP, а другой — внешний диск, подключенный через FireWire. Это не имеет значения, потому что я скопировал оба каталога локально, и сравнение заняло одинаковое количество времени.

У меня есть решение этой проблемы: я запускал ls -1 для обоих каталогов и производил сравнение вывода, но почему diff выполняется так долго?

Вот код; какие-либо предложения?

#!/bin/bash

before="$(date +%s)"

diff -r -x '.*' /Volumes/directory1/ /Volumes/directory2/ | sed 's/^.\{24\}//g' > /Volumes/stuff.txt
diff -r -x '.*' /Volumes/directory3/ /Volumes/directory4/ | sed 's/^.\{24\}//g' > /Volumes/stuff.txt
diff -r -x '.*' /Volumes/directory5/ /Volumes/directory6/ | sed 's/^.\{24\}//g' > /Volumes/stuff.txt
diff -r -x '.*' /Volumes/directory7/ /Volumes/directory8/ | sed 's/^.\{24\}//g' > /Volumes/stuff.txt
diff -r -x '.*' /Volumes/directory9/ /Volumes/directory10/ | sed 's/^.\{24\}//g' > /Volumes/stuff.txt
diff -r -x '.*' /Volumes/directory11/ /Volumes/directory12/ | sed 's/^.\{24\}//g' > /Volumes/stuff.txt

after="$(date +%s)"
elapsed_seconds="$(expr $after - $before)"
echo Elapsed time for code block: $elapsed_seconds

person rick    schedule 17.03.2011    source источник


Ответы (1)


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

Если все, что вам нужно, это различия в именах файлов и вы не хотите проверять содержимое файлов, попробуйте что-то вроде:

diff <(find /Volumes/directory1/ -printf '%P\n') \
     <(find /Volumes/directory2/ -printf '%P\n')

Это предполагает, что у вас есть GNU find с действием -printf. Если вы этого не сделаете, используйте некоторую магию подоболочки в соответствии с комментарием Гордона:

diff <(cd /Volumes/directory1; find .) \
     <(cd /Volumes/directory2; find .)
person John Kugelman    schedule 17.03.2011
comment
Если у вас нет GNU find, это должно работать: diff <(cd /Volumes/directory1; find .) <(cd /Volumes/directory2; find .) - person Gordon Davisson; 18.03.2011
comment
@gordon спасибо, это определенно на правильном пути (поскольку я на Mac OS X и у меня нет GNU find). Вы можете объяснить, что происходит? похоже, вы находите разницу в выводе find . в обоих каталогах? - person rick; 18.03.2011
comment
спасибо, это имеет смысл, так как он всегда сразу же находит разницу, а затем оставшиеся 80 с лишним минут ничего не говорит. - person rick; 18.03.2011
comment
@rick: И версия Джона, и моя версия используют find для создания списка имен файлов в каталоге (и его подкаталогах), а затем сравнивают списки. Поскольку он извлекает и сравнивает только имена файлов, а не их содержимое, он будет работать очень быстро (но не обнаружит, есть ли в двух каталогах файлы с совпадающими именами, но с разным содержимым). - person Gordon Davisson; 18.03.2011
comment
классный трюк! у меня оба работают, но find . легче набирать, хех. На самом деле я сделал обобщение, передав $1 и $2 в скрипт с именем mydiff.sh, чтобы он был под рукой ;) diff <(cd $1; find .) <(cd $2; find .) - person Xavi Montero; 13.02.2014
comment
Поиск в двух разных каталогах может привести к результатам в разном порядке. Команда в ответе обнаружила, что почти все по-другому. В моем случае я считаю, что это было вызвано тем, что один из каталогов находился в смонтированном каталоге CIFS. Добавление сортировки к каждой команде поиска помогло: diff <(find dir1 -printf '%P\n'|sort) <(find dir2 -printf '%P\n'|sort) - person Wesley Hartford; 02.02.2016