
다음 문제에 대한 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
이 의사 코드에 선호하는 셸을 사용하면 다음과 같습니다.
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
이것은 dups 복사를 위한 mpez0의 ans와 마찬가지로 작업을 수행할 수 있습니다.
find {tst1,tst2} -exec sum {} {} \; 2> /dev/null | sort | uniq