Найти файлы, которых нет в других каталогах

Найти файлы, которых нет в других каталогах

Мне нужно найти все файлы, которые существуют где-либо в dir1, но не существуют где-либо в dir2. dir1и dir2могут иметь другую структуру, поэтому diff -rэто не работает должным образом.

решение1

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

find dir1/ -exec basename {} \; | sort
find dir2/ -exec basename {} \; | sort

Все вместе будет выглядеть примерно так

diff <(find dir1/ -exec basename {} \; | sort) <(find dir2/ -exec basename {} \; | sort)

Я вижу, что есть комментарий, предлагающий использовать fdupes. fdupesЕсли это определенно лучшее решение.

решение2

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

find /first/path -type f -exec md5sum -b \{\} \; > /tmp/md5-path1.txt
cut -b1-32 < /tmp/md5-path1-short.txt
find /second/path -type f -exec md5sum -b \{\} \; > /tmp/md5-path2.txt
cut -b1-32 < /tmp/md5-path2-short.txt

Файлы в path1, которых нет в path2 (удалите опцию '-v')

grep /tmp/md5-path1.txt -v -F -f /tmp/md5/path2-short.txt

Уровень CYA: профессиональный

32 выше — это потому, что хэши MD5 имеют длину 32 байта. Если бы вы использовали, скажем, sha1sum, что имеет еще меньшую вероятность коллизий, то вы бы использовали длину 40; sha224sumтребует 56, sha256sumтребует 64 и sha512sum128.

Уровень CYA: параноидальный

Это может не работать в некоторых схемах кэширования, в которых метаданные хранятся в файлах.имя которого содержит хэш исходного файла.

(Это на самом деле произошло со мной несколько лет назад при установке Wordpress + Magento, когда мы хотели перенести огромный кэш статей, удалив при этом устаревшие записи).

В этом случае вам придется использовать другую схему хеширования — быстрое исправление — чтобы избежать grepвозврата ложных срабатываний, ошибочно принимая запись метаданных за исходный файл (поэтому используйте SHA1, если кэш использует MD5, или наоборот); или использовать sedдля переписывания всех строк в «коротких» файлах, чтобы добавить «^» в начале, таким образом превратив его в закрепленное регулярное выражение, и снять флаг -Fс grepдля обработки файла как регулярных выражений, а не как простых строк.

решение3

Итак, частичное решение, которое я нашел, это:

find dir1 -type f | grep -vxFf <(fdupes -r dir1 dir2)

но я говорю «частично», потому что если в , то они не будут показаны, поэтому сначала dir1нужно запустить .fdupes -r dir1

Связанный контент