예를 들어 20200403과 같은 날짜로 시작하는 많은 파일이 있는 폴더가 있습니다. 동일한 날짜의 여러 파일이 있는 폴더를 찾고 싶습니다. 즉, 처음 8자가 동일합니다. 날짜는 각 특정 폴더 내에서만 중요합니다. 폴더 간에는 중요하지 않습니다.
파일 메타데이터가 파일 이름 날짜와 반드시 일치할 필요는 없으므로 이를 찾는 방법으로 사용할 수 없습니다.
답변1
적절하게 정렬된 파일 이름 목록을 전달하는 것을 고려할 수 있습니다 uniq -d
. uniq
예를 들어, 쉘이 데이터 정렬에 대해 동일한 아이디어를 가지고 있다고 가정합니다.
printf -- "%s\n" * | cut -c1-8 | uniq -d
결과가 비어 있지 않으면 중복 항목이 있어야 합니다. find
다음 명령 으로 감싸세요 .
find . -type d -exec sh -c '
cd "$1" && test -n "$(printf -- "%s\n" * | cut -c1-8 | uniq -d)"
' find-sh {} \; -print
그래서 주어진
$ tree .
.
├── subdir1
│ └── 20200403foo
├── subdir2
│ ├── 20200403bar
│ └── 20200403foo
├── subdir3
│ └── 20200403foo
├── subdir4
│ ├── 20200403bar
│ └── 20200403foo
└── subdir5
└── 20200403foo
5 directories, 7 files
그 다음에
$ find . -type d -exec sh -c 'cd "$1" && test -n "$(printf -- "%s\n" * | cut -c1-8 | uniq -d)"' find-sh {} \; -print
./subdir4
./subdir2
줄 바꿈을 포함하고 빈 구분 기호를 지원하는 파일 이름을 처리해야 하는 경우 파이프를 다음으로 변경할 수 있습니다 cut
.uniq
printf "./%s\0" * | cut -zc1-10 | uniq -zd
답변2
개행 문자를 포함하여 임의의 파일 경로를 올바르게 처리하지만 어느 정도 우아하지 않고 느릴 수 있는 이식 가능한 솔루션입니다.
find /path/to/dir -type d \( -exec sh -c '
cd "$1"
printf "%s/" [0123456789][0123456789][0123456789][0123456789][01][0123456789][0123][0123456789]* \
| awk -v RS="/" "seen[substr(\$0,1,8)]++ { exit 1 }"
' mysh {} \; -o -print \)
find
디렉터리를 재귀적으로 검색하고 /path/to/dir
대략 날짜와 유사한 패턴(yyyy/mm/dd 형식으로 가정)과 일치하는 파일 이름을 파이프하는 검색된 각 디렉터리에서 스크립트를 실행하는 데 사용됩니다. /
로 끝나는 구분된 레코드를 읽는 각 스크립트 인스턴스는 상태로 종료됩니다. awk
input 에서 반복되는 8자(첫 번째 문자부터 시작) 문자열이 발견 되 /
자마자 디렉터리 이름이 편집됩니다.1
-print
GNU 도구를 기반으로 한 더 빠른 대안:
find /path/to/dir -type f -name '[0123456789][0123456789][0123456789][0123456789][01][0123456789][0123][0123456789]*' \
-print0 | awk -v FS='/' -v OFS='/' -v RS='\0' '
{ file=substr($NF,1,8); $NF=""; dir=$0 }
seen[dir file]++ { dupl[dir] }
END { for (d in dupl) print d }'
여기서는 이름이 (대략) 날짜로 시작하는 일반 파일만 으로 파이프됩니다 /path/to/dir
. 발견된 파일 경로는 awk
NUL로 구분된 레코드 스트림으로 파이프됩니다. 각 레코드에 대해 마지막 구성 요소(파일 이름)의 처음 8자만 유지되고 결과 경로는 연관 배열에 저장됩니다. 중복 항목이 발견되면 디렉터리 부분(즉, 파일 이름 부분이 제거된 경로)이 인쇄됩니다.