从两个目录提取相同的文件

从两个目录提取相同的文件

我正在寻找以下问题的 Linux 解决方案:

给定两个包含大量文件的目录。所有文件名都是随机的,且两个目录中的文件名称不同。但是两个目录中某些文件的内容相同。

我想将两个目录中出现的所有文件复制到第三个目录中。(“同时出现在两个目录中”表示内容相同,但名称不同。)

答案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

(同样,如果文件名称中可能包含空格,那么这种方法将不起作用。)

答案2

使用你最喜欢的 shell 来执行此伪代码:

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 输出以供审查

答案3

这可能会完成工作,就像 mpez0 复制重复项一样。

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

相关内容