트리에서 모든 최종 서브 디렉토리를 찾으십시오


11

다음과 같은 구조가 주어집니다.

oz123@debian:~/ $ tree .
.
├── a
│   ├── a1
│   ├── a2
│   └── a3
├── a1
│   ├── a11
│   ├── a12
│   └── a31
├── b
│   └── b1
│       ├── b11
│       │   └── b21
│       │       └── b31
│       ├── b12
│       └── b3
└── c

16 directories, 0 files

모든 엔드 노드를 어떻게 찾습니까?

나는 다음과 같은 솔루션을 찾을 것 같습니다 좋은 수를,하지만 난 그것을 실패 테스트 케이스가 아님을 증명해야합니다.

상태의 도움말 페이지 -links:

'-links'를 사용하여 특정 수의 링크가있는 파일을 검색 할 수도 있습니다. 디렉토리에는 일반적으로 두 개 이상의 하드 링크가 있습니다. 그들의. 항목이 두 번째입니다. 하위 디렉토리가있는 경우 각 디렉토리에도 상위 디렉토리에 대한 .. 하드 링크가 있습니다. . .. 디렉토리 항목은 find 명령 행에 언급되지 않는 한 정상적으로 검색되지 않습니다.

가능한 해결책:

oz123@debian:~/ $ find .  -type d  -links 2
./a/a2
./a/a3
./a/a1
./c
./a1/a31
./a1/a11
./a1/a12
./b/b1/b12
./b/b1/b3
./b/b1/b11/b21/b31
  • 누구나 더 나은 솔루션을 제공 할 수 있습니까 (파이프 및 sed를 사용하지 않고도 성능이 뛰어납니다 ...)
  • 모든 파일 시스템에서 작동합니까?

3
-links 2트릭 보다 성능이 뛰어나지 않습니다. 작동하지 않습니다 btrfs.
Stéphane Chazelas

답변:


3

을 사용하는 자체 솔루션 외에도 -linksUnix 디렉토리 링크 규칙을 따르지 않는 파일 시스템에서는 작동하지 않는다는 것을 추가하고 싶습니다. 에서 man find옵션에 대한 -noleaf다음은, 적어도 CD-ROM에있는 MS-DOS 파일 시스템과 AFS 볼륨 마운트 포인트.

참고 로이 질문은 실제로 다른 솔루션으로 이미 논의되었으며 실제로는 느리고 일반적으로 sed / awk와 유사한 파이프에 의존합니다.


3

조금 더 확실한 옵션이 있습니다 -empty.

find . -type d -empty

올라 갔다. 좋아, 당신은이 방법으로 옳지 않은 파일로 작업하지 않을 것입니다.

따라서 고정 파일 시스템의 독립 버전입니다.

find dtest/ -type d -exec sh -c "if [ \$(find {} -maxdepth 1 -type d | wc -l) -eq 1 ]; then echo {} ; fi" \;

2
질문을 이해하면 엔드 디렉토리에 파일이 포함될 수 있습니다. 이 디렉토리는 "빈"것이 아니기 때문에 해당 디렉토리를 인쇄하지 않습니다 ...
Stefan

@rush, 하위 디렉토리는 비워 둘 수 있습니다
Oz123

@ Oz123 내 업데이트를 확인하십시오. 충분히 빠르지 만 귀하의 방식에 비해 조금 느립니다.
rush

@ rush, 고마워하지만 파이프를 피해야합니다. 속도가 느려질 수 있습니다.
Oz123

1

find . -type d -links 2대부분의 파일 시스템에서 작동하지만 전부는 아닙니다. 디렉토리에 자신에 대한 링크가 포함되어있는 속성을 가진 파일 시스템 유형을 아는 것 외에는 알 수있는 방법이 없다고 생각합니다. GNU find는 이것을 동적으로 감지합니다 (“find -noleaf 옵션 자동 켜기”에 관한 내용을 인쇄하면 파일 시스템에이 속성이없는 것입니다). 가장 일반적인 파일 시스템 유형은 정상이지만 FAT 또는 btrfs는 아닙니다.

확실하게하려면 각 디렉토리를 테스트해야합니다. 이를 수행하는 한 가지 방법 find은 각 서브 디렉토리에 대해 다시 호출하는 것입니다.

find . -type d ! -exec sh -c '
   find "$1/." ! -name . -type d -prune | grep -q "^"' sh {} \; -print

(GNU와 함께 find, 당신은 대체 할 수있는 -prune-print -quit가 좀 더 효율적으로 만드는).

다른 방법은의 출력을 후 처리하는 것입니다 find. 을 사용 find -depth하면 리프 디렉토리는 자체의 서브 디렉토리를 따르지 않는 디렉토리입니다.

find . -depth -type d -print0 |
awk -v RS='\0' '
    substr(previous, 1, length($0) + 1) != $0 "/"
    { previous = $0 }
'

0

다음 솔루션을 시도하십시오 (Linux, Unix 및 OS X 호환 가능).

find . -type d -execdir sh -c 'test -z "$(find "{}" -mindepth 1 -type d)" && echo $PWD/{}' ';'

파이프가없는 서두 솔루션 과 비슷한 접근 방식 입니다.

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