다양한 파일이 포함된 중첩된 디렉터리 구조가 주어지면 그 안에 있는 모든 파일을 찾고 싶지만, 동일한 이름을 가진 파일이 여러 개 있으면 가장 큰 파일만 반환하고 싶습니다.
예를 들어 다음과 같은 디렉토리 구조가 있다고 가정해 보겠습니다.
|--- 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).