둘 이상의 파일이있는 디렉토리


11

현재 디렉토리의 하위 디렉토리 (하위 디렉토리)에 둘 이상의 일반 파일이 포함되어 있습니다.

파일이 2 개 미만인 디렉토리 나 하위 디렉토리 만있는 디렉토리에는 관심이 없습니다.

답변:


12

다음은 GNU find와에 기반한 완전히 다른 접근법입니다 uniq. 이것은 발견 된 각 디렉토리의 파일을 계산하는 쉘 명령을 실행하는 것에 대한 응답보다 훨씬 빠르고 CPU 친화적입니다.

find . -type f -printf '%h\n' | sort | uniq -d

find명령은 계층 구조에있는 모든 파일의 디렉토리를 인쇄하고 uniq두 번 이상 나타나는 디렉토리 만 표시합니다.


2
의 출력을 구문 분석해서는 안됩니다 find. 이 경우, GNU find는 현재 로케일에서 인쇄 할 수없는 문자 (C 로케일의 "ä")가있는 디렉토리 이름을 맹 글링 하기 때문 입니다. 참조 unix.stackexchange.com/questions/321697/...
Kusalananda

4
@Kusalananda, 출력이 tty로 가지 않을 때가 아닙니다. 여기서 유일한 문제는 줄 바꿈 문자에 관한 것입니다.-printf '%h\0' | sort -z | uniq -zd | xargs -r0 ...
Stéphane Chazelas

6
find . -type d \
    -exec sh -c 'c=0; for n in "$1"/*; do [ -f "$n" ] && [ ! -h "$n" ] && c=$(( c + 1 )); done; [ "$c" -ge 2 ]' sh {} ';' \
    -print

현재 디렉토리 내 또는 아래에서 모든 이름을 찾은 다음 디렉토리 이름이 아닌 모든 이름을 필터링합니다.

나머지 디렉토리 이름은이 짧은 스크립트에 제공됩니다.

c=0
for n in "$1"/*; do
    [ -f "$n" ] && [ ! -h "$n" ] && c=$(( c + 1 ))
done

[ "$c" -ge 2 ]

이 스크립트는 첫 번째 명령 행 인수 (from find) 로 제공된 디렉토리의 일반 파일 (심볼 링크 건너 뛰기) 수를 계산합니다 . 스크립트의 마지막 명령은 개수가 2 이상인지 확인하는 테스트입니다. 이 테스트의 결과는 스크립트의 반환 값 (종료 상태)입니다.

테스트가 성공하면, -print원인이됩니다 find디렉토리의 경로를 출력 할 수 있습니다.

숨겨진 파일 (이름이 점으로 시작하는 파일)도 고려하려면 sh -c스크립트에서

for n in "$1"/*; do

for n in "$1"/* "$1"/.*; do

테스트 :

$ tree
.
`-- test
    |-- a
    |-- dir1
    |   |-- a
    |   |-- b
    |   `-- c
    `-- dir2
        |-- dira
        |-- dirb
        |   |-- file-1
        |   `-- file-2
        `-- dirc

6 directories, 6 files

$ find . -type d -exec sh -c 'c=0; for n in "$1"/*; do [ -f "$n" ] && [ ! -h "$n" ] && c=$(( c + 1 )); done; [ "$c" -ge 2 ]' sh {} ';' -print
./test/dir1
./test/dir2/dirb

솔루션은 이름이 점으로 시작하는 파일을 계산하지 않습니다. 파일이없는 디렉토리의 오류 메시지를 피하려면 c = 0을 초기화해야합니다.
xhienne

@xhienne 숨겨진 파일을 고려하여 메모를 추가합니다. [ "" -ge 2 ]유효한 테스트 이므로 디렉토리에 일반 파일이 없으면 오류가 없습니다 .
Kusalananda

"유효한"정의 방법을 잘 모르겠습니다. POSIX는 arg1이 정수 값이어야합니다. dash, bash --posix그리고 test모든 디스플레이는 2 오류 메시지 종료 (즉 "는 오류가 발생했습니다")
xhienne

@xhienne 아, 나는로 ksh실행 되는 시스템에서 테스트하고있었습니다 sh. 즉시 수정합니다. 나를 파고 주셔서 감사합니다! :-)
Kusalananda

또한 [ -f ... ]심볼릭 링크를 역 참조합니다. 질문에 일반 파일 만 계산되도록 지정되어 있으므로 제거하기위한 테스트를 추가해야합니다.
xhienne

6

의 도움으로 질의 대답SU 와 그 역 및 일부 수정이 필요 여기서 뭐.

find . -type d -exec sh -c 'set -- "$1"/*;X=0; 
    for args; do [ -f "$args" ] && X=$((X+1)) ;done; [ "$X" -gt 1 ] ' _ {} \; -print

디렉토리 트리.

.
├── test
│   ├── dir1
│   │   ├── a
│   │   ├── b
│   │   └── c
│   ├── dir2
│   │   ├── dira
│   │   │   └── a file\012with\012multiple\012line
│   │   ├── dirb
│   │   │   ├── file-1
│   │   │   └── file-2
│   │   └── dirc
│   ├── diraa
│   ├── dirbb
│   ├── dircc
│   └── x
│   └── x1
│   └── x2
└── test2
    ├── dir3
    └── dir4

결과:

./test
./test/dir1
./test/dir2/dirb

처음에는 이것을 가지고 있었지만 여러 하위 디렉토리 파일을 포함하는 디렉토리에 문제가 있습니다. 또한 서브 디렉토리 만 포함 된 디렉토리를 제거하지는 않습니다.
Kusalananda

실제로 해결되지는 않습니다. 테스트 설정에서 testdir2디렉토리를 모두 찾습니다 (내 답변 참조).
Kusalananda

하지만 예를 들어 작품, 추가 test/x1test/x2뿐만 아니라 파일과 같은 ... $1$2에 대한 디렉토리 것 test, 그리고 디렉토리 놓칠 수 있습니다.
Kusalananda

@ Kusalananda 나는 당신이 대답 한 것을 제외하고는 찾을 수 없었습니다. 나는 명령의 일부를 변경하여 당신의 사본과 정확하게 일치하지 않도록 노력했습니다 (숨겨진 파일은 제외하지 않았습니다), 사과드립니다.
αғsнιη

1
걱정 마세요 :-)
Kusalananda

3

또 다른 find+ wc접근법 :

find path/currdir -maxdepth 1 -type d ! -empty ! -path "path/currdir" \
-exec sh -c 'count=$(find "$1" -maxdepth 1 -type f | wc -l); [ $count -ge 2 ]' _ {} \; -print

  • path/currdir -현재 디렉토리 경로

  • -maxdepth 1- 직접 하위 하위 폴더 만 고려

  • ! -empty -빈 하위 폴더 무시

  • ! -path "path/currdir" -현재 디렉토리 경로를 무시

  • count=$(find "$1" -maxdepth 1 -type f | wc -l)- count발견 된 각 하위 폴더에 대한 파일 수가 지정됩니다.

  • [ $count -ge 2 ] ... -print -2 개 이상의 정규 파일을 포함하는 하위 폴더 이름 / 경로 인쇄

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.