내가 달성하고 싶은 것은 디렉토리의 모든 파일을 가져와서 내용의 고유성에 따라 나열/정렬하는 것입니다.
예:
우리 디렉토리에 다음과 같은 7개의 파일이 있다고 가정합니다.
uniquefile1.txt, uniquefile2.txt, samefile1.txt, samefile2.txt, equalfile1.txt, equalfile2.txt, equalfile3.txt
여기서 Uniquefile1과 Uniquefile2의 내용은 서로 다르며, 모든 Samefile.txt는 서로 동일한 내용을 가지며, 모든 Equalfile.txt는 서로 동일한 내용을 갖습니다.
예상 출력:
uniquefile1.txt
uniquefile2.txt
samefile1.txt, samefile2.txt
equalfile1.txt, equalfile2.txt, equalfile3.txt
나는 해싱과 md5sum을 사용해 왔지만 이 작업을 수행하기 위해 아무것도 얻을 수 없었습니다.
필요한 경우 grep, xargs, sed, awk, find 및 located와 같은 유틸리티를 다른 coreutil과 혼합하여 이 작업을 수행하고 싶습니다.
답변1
수정된 부분입니다어제 쓴 답변:
$ cksum file* | awk '{ ck[$1$2] = ck[$1$2] ? ck[$1$2] ", " $3 : $3 } END { for (i in ck) print ck[i] }'
file3, file5
file1, file2, file4
*.txt
귀하의 경우에는 대신에 또는 even *
(비교하려는 디렉터리에 파일만 있는 경우)을 사용합니다 file*
.
결과는 file3
and가 and file5
와 동일한 내용을 가지고 있음 을 알려줍니다 ( 이 경우).file1
file2
file4
표준 cksum
유틸리티는 각 파일에 대해 세 개의 열을 출력합니다. 첫 번째는 체크섬이고, 두 번째는 파일 크기, 세 번째는 파일 이름입니다.
코드 awk
는 체크섬과 크기를 배열의 키로 사용 ck
하고 해당 키에 대해 쉼표로 구분된 문자열에 동일한 키를 가진 파일 이름을 저장합니다. 마지막으로 파일 이름(쉼표로 구분된 문자열)을 인쇄합니다.
웃기게 생긴
ck[$1$2] = ck[$1$2] ? ck[$1$2] ", " $3 : $3
ck[$1$2]
" 무엇이든 설정하면 할당 ck[$1$2] ", " $3
( ck[$1$2]
파일 이름 사이에 쉼표 추가)하고, 그렇지 않으면 할당 $3
(이 키가 있는 첫 번째 파일 이름)"을 의미합니다 .
각 목록의 항목 수를 기준으로 출력을 정렬하려면 출력을 다음으로 전달합니다.
awk -F, '{ print NF, $0 }' | sort -n | cut -d ' ' -f 2-
...후처리 단계입니다. 파일 이름에 쉼표가 포함되어 있으면 분명히 깨질 것입니다.
또는 사용
cksum file* | awk '{ n[$1$2]++; ck[$1$2] = ck[$1$2] ? ck[$1$2] ", " $3 : $3 } END { for (i in ck) print n[i], ck[i] }' | sort -n | cut -d ' ' -f 2-
파일 이름에 쉼표가 있으면 아무런 문제가 없습니다.
cut
각 출력 줄의 파일 이름 수를 보려면 이 옵션을 무시하십시오.
많은 수의 파일에 사용할 수 있습니다.
find . -type f -exec cksum {} +
그리고 뿐만 아니라
cksum *
답변2
나는 다음을 사용할 것이다 perl
:
perl -MDigest::SHA -le '
for $f (@ARGV) {
$d = Digest::SHA->new(256);
$d->addfile($f);
push @{$h{$d->digest}}, $f
}
print join ", ", @{$h{$_}} for keys %h' -- *.txt
우리는 키가 파일의 sha256 해시이고 값이 해당 해시가 있는 파일 목록인 연관 배열을 구축하고 있습니다.
발생 횟수에 따라 출력을 쉽게 정렬할 수 있습니다. 예를 들면 다음과 같습니다.
perl -MDigest::SHA -le '
for $f (@ARGV) {
$d = Digest::SHA->new(256);
$d->addfile($f);
push @{$h{$d->digest}}, $f
}
print join ", ", @{$h{$_}} for sort {@{$h{$a}} <=> @{$h{$b}}} keys %h' -- *.txt
또는 각 그룹의 파일 목록을 파일 이름별로 정렬할 수도 있습니다.
perl -MDigest::SHA -le '
for $f (@ARGV) {
$d = Digest::SHA->new(256);
$d->addfile($f);
push @{$h{$d->digest}}, $f
}
print join ", ", sort {$a cmp $b} @{$h{$_}} for
sort {@{$h{$a}} <=> @{$h{$b}}} keys %h' -- *.txt