내용을 기반으로 모든 파일을 나열하는 Bash 명령

내용을 기반으로 모든 파일을 나열하는 Bash 명령

내가 달성하고 싶은 것은 디렉토리의 모든 파일을 가져와서 내용의 고유성에 따라 나열/정렬하는 것입니다.

예:

우리 디렉토리에 다음과 같은 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*.

결과는 file3and가 and file5와 동일한 내용을 가지고 있음 을 알려줍니다 ( 이 경우).file1file2file4

표준 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

관련 정보