Я ищу решение Linux для следующей проблемы:

Даны две директории с большим количеством файлов. Все имена файлов случайные и разные в обоих каталогах. Однако содержимое некоторых файлов в этих двух каталогах идентично.

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

3 ответа3

1

Предполагая, что в именах ваших файлов нет пробелов и в подкаталогах нет ни одного подкаталога, следующее выведет пары имен файлов с соответствующими суммами MD5:

join -o 1.2,2.2 <(md5sum $D1/* | sort) <(md5sum $D2/* | sort)

Чтобы получить только одно из имен файлов, используйте -o 1.2 или -o 2.2 .

Если имена файлов (или пути) могут содержать пробелы, вам нужно быть более умным.

Если в одном каталоге может быть один и тот же файл с более чем одним именем, вам также нужно быть более умным - и вам нужно будет точно решить, что делать. Одной из возможностей будет отфильтровать дубликаты перед выполнением объединения:

join -o 1.2,2.2 <(md5sum $D1/* | sort | uniq -w16) \
                <(md5sum $D2/* | sort | uniq -w16)

НЕ ИСПОЛЬЗУЙТЕ sum

sum выводит 16-битную контрольную сумму; если у вас есть даже пара сотен файлов в каждом каталоге, вполне вероятно, что вы получите ложное срабатывание при сравнении 16-битных контрольных сумм. md5sum не является абсолютно безопасным, но вероятность столкновения с 128-битными контрольными суммами ничтожна. В случае сомнений и, если это действительно важно, также cmp файлы:

join -o 1.2,2.2 <(md5sum $D1/* | sort) <(md5sum $D2/* | sort) |
while read F1 F2; do
  if cmp -s $F1 $F2; then
    cp F1 $D3
  fi
done

(Опять же, это не сработает, если у файлов могут быть пробелы в именах.)

0

Используя вашу любимую оболочку для этого псевдокода:

cd D1; sum * | while read l; do echo "D1 $l"; done >/tmp/foo
cd D2; sum * | while read l; do echo "D2 $1"; done >>/tmp/foo

sort -n /tmp/foo | awk '
$1 == prev_cs { echo "cp $3 dest"}
     /prev_cs = $1/
' | shell

Вы можете сохранить выходные данные awk для просмотра перед выдачей копий, если хотите

0

это может сделать работу, как в случае с mpez0 для копирования дубликатов.

find {tst1,tst2} -exec sum {} {} \; 2> /dev/null | sort | uniq

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .