재귀적으로 파일을 찾지만 이름이 중복된 파일 중에서 가장 큰 파일을 선택합니다.

재귀적으로 파일을 찾지만 이름이 중복된 파일 중에서 가장 큰 파일을 선택합니다.

다양한 파일이 포함된 중첩된 디렉터리 구조가 주어지면 그 안에 있는 모든 파일을 찾고 싶지만, 동일한 이름을 가진 파일이 여러 개 있으면 가장 큰 파일만 반환하고 싶습니다.

예를 들어 다음과 같은 디렉토리 구조가 있다고 가정해 보겠습니다.

|--- foo.jpg (110 KB)
|--- bar.jpg (210 KB)
|--- dir
      |----- foo.jpg (860 KB)
      |----- baz.jpg (200 KB)

출력 라인을 생성하고 싶습니다(순서는 중요하지 않습니다).

bar.jpg
dir/foo.jpg
dir/baz.jpg

가급적 bash에서 이 작업을 수행하려면 어떻게 해야 합니까?

답변1

@UlrichSchwarz의 의견을 구체화하기 위해 다음과 같이 마무리했습니다.

find . -type f -printf "%s %P %f\n" | sort -k3,3 -k1,1rn | uniq -f 2 | cut -f 2 -d ' '

편집하다예를 들어 공백이 있는 파일 이름은 처리되지 않습니다. 보다 강력한 솔루션은 @StéphaneChazelas의 솔루션을 참조하세요.

답변2

그리고 zsh:

typeset -A files
for f (**/*(D.oL)) files[$f:t]=$f
printf '%s\n' $files

파일 이름에 포함될 수 있는 모든 바이트나 문자(공백, 줄 바꿈 등)를 사용할 수 있습니다.

GNU 도구 사용:

find . -type f -printf '%s/%f/%P\0' |
  sort -zrn |
  LC_ALL=C sort -zt/ -uk2,2 |
  tr '\0\n' '\n\0' |
  cut -d/ -f3- |
  tr '\0' '\n'

중복을 제거하려면 다음을 사용하십시오 zsh.

allfiles=(**/*(D.oL))
typeset -A best
for f ($allfiles) best[$f:t]=$f
bestfiles=($best)
dups=(${allfiles:|bestfiles})
rm -rf -- $dups

zsh의 일부 기능 설명:

  • typeset -A best: ksh93과 같이 연관배열 변수를 선언합니다. 최신 버전 bash도 지원합니다.
  • **/*: 재귀적 와일드카드. 90년대 초반에 zsh에 의해 도입된 이 버전의 변형은 현재 일부 다른 셸에서 발견됩니다.
  • (D.oL): 와일드카드 한정자. 재귀 와일드카드의 중요한 동반자이기는 하지만 아직 다른 쉘에 의해 복사되지 않은 또 다른 zsh 발명품입니다. 글로브를 추가로 한정하는 데 사용됩니다. 다음을 포함하는 D도트 파일을 포함합니다 ..정기적인oL길이(바이트 단위)로 정렬된 파일입니다 .
  • ${file:t}: (t)csh와 마찬가지로 다음으로 확장됩니다.꼬리파일 이름(기본 이름)의 일부입니다.
  • ${a:|b}a에 존재하지 않는 요소로 확장됩니다 b. (ab).

관련 정보