하위 디렉터리 없이 디렉터리만 찾는 방법은 무엇입니까? [복사]

하위 디렉터리 없이 디렉터리만 찾는 방법은 무엇입니까? [복사]

Linux에는 디렉토리 트리에서 브랜치의 끝(여기서는 나뭇잎이라고 부르겠습니다)인 디렉토리, 즉 하위 디렉토리가 없는 디렉토리만 찾는 방법이 있습니까? 내가 찾고 있어요이 문제하지만 한번도 제대로 된 답을 얻지 못했습니다.

그래서 디렉토리 트리가 있다면

root/
├── branch1
│   ├── branch11
│   │   └── branch111   *
│   └── branch12        *
└── branch2
    ├── branch21        *
    └── branch22
        └── branch221   *

분기 끝( 레이블이 붙은 디렉터리 *)에서만 디렉터리를 찾을 수 있으므로 파일 수가 아닌 디렉터리 수만 볼 수 있습니까? 실제 사례에서는 파일이 포함된 파일을 찾고 있지만 해당 파일은 이 예에서 찾고자 하는 "나뭇잎"의 하위 집합입니다.

답변1

디렉터리가 아닌 파일이 포함된 리프 디렉터리만 찾으려면 인용된 질문에 대한 답변을 결합하면 됩니다.https://unix.stackexchange.com/a/203991/330217또는 비슷한 질문https://stackoverflow.com/a/4269862/10622916또는https://serverfault.com/a/530328find와 함께! -empty

find rootdir -type d -links 2 ! -empty

하드 링크 확인은 -links 2기존 UNIX 파일 시스템에서 작동합니다. 이 -empty조건은 POSIX 표준의 일부는 아니지만 대부분의 Linux 시스템에서 사용할 수 있습니다.

KamilMaciorowski의 의견에 따르면 디렉토리의 전통적인 링크 수 의미는 Btrfs에 유효하지 않습니다. 이것은https://linux-btrfs.vger.kernel.narkive.com/oAoDX89D/btrfs-st-nlink-for-directoriesMac OS HFS+는 기존 동작에 대한 예외로도 언급됩니다. 이러한 파일 시스템의 경우 리프 디렉터리를 확인하려면 다른 방법이 필요합니다.

답변2

find중첩을 사용 하고 하위 디렉터리 수를 계산할 수 있습니다 .

find . -type d \
  \( -exec sh -c 'find "$1" -mindepth 1 -maxdepth 1 -type d -print0 | grep -cz "^" >/dev/null 2>&1' _ {} \; -o -print \)

답변3

그리고 zsh:

leafdirs=( **/*(NDFl2) )

$leafdirs일치하는 리프 디렉터리 목록으로 배열을 설정합니다.

다음을 사용하여 열에 aw를 print나열 할 수 있습니다 .r1 C

print -rC1 -- $leafdirs

또는 다음을 사용하여 반복합니다.

for dir ($leafdirs) something with $dir

이건 거의 번역이네@Bodo의 GNU find답변, 이는 전통적인 Unix 계열 파일 시스템( ext4이 구현과 같은) ...실제 디렉토리 항목에서만 작동하는 것과 같습니다.

  • **/: 모든 수준의 하위 디렉터리
  • (NDFl2): 글로벌 예선
  • N: nullglob이 glob을 활성화합니다. 일치하는 항목이 없어도 실패하지 않습니다. 대신 결과는 빈 목록입니다.
  • D: 이 glob 활성화 dotglob: 숨겨진 디렉터리를 보고 숨겨진 파일을 건너뛰지 않습니다.
  • F: 선택하다가득한디렉토리: .및 이외의 항목이 하나 이상 포함된 디렉토리 ..(GNU find와 유사 -type d ! -empty)
  • l2: 개수가 2개인 디렉터리만 연결합니다(예: -links 2). 하나는 상위 디렉토리의 디렉토리 항목용이고 다른 하나는 .상위 디렉토리 내의 디렉토리 항목용입니다. 모든 하위 디렉토리에는 해당 항목 으로 인해 ..링크 수에 하나가 추가됩니다 .

nlinks == 2가 불가능한 파일 시스템에서는 다음을 수행할 수 있습니다.

leafdirs=( **/*(NDF^e['()(($#)) $REPLY/*(ND/Y1)']) )

(이 코드에 저장된) 디렉터리에 하위 디렉터리가 있는지 확인하기 위해 e한정자(negation 포함 )를 사용하여 코드를 실행합니다 . 여기서는 익명 함수를 사용하여 디렉터리 확장이 첫 번째 일치에서 중지되는지 확인합니다. 전달된 인수는 A입니다. 비어 있지 않은 목록(0이 아님).^$REPLY$REPLY/*(ND/Y1)$REPLY$#

답변4

파일 이름 와일드카드 패턴이 디렉터리 이름이 아닌 다른 이름으로 확장 되면 */현재 디렉터리에 숨겨진 하위 디렉터리가 없는 것입니다.

그리고 find:

find root -type d -exec sh -c 'set -- "$1"/*/; [ ! -d "$1" ]' sh {} \; ! -empty -print

패턴이 심볼릭 링크를 통과하므로 리프 디렉터리에 있는 디렉터리에 대한 심볼릭 링크를 디렉터리로 처리합니다.

-empty술어는 표준은 아니지만 자주 구현됩니다. 이것이 없으면 하위 디렉터리를 검색하는 것과 유사한 작업을 수행하게 됩니다.

find root -type d \
    -exec sh -c 'set -- "$1"/*/; [ ! -d "$1" ]' sh {} \; \
    -exec sh -c 'set -- "$1"/*;  [   -e "$1" ]' sh {} \; -print

또는 더 효과적으로,

find root -type d -exec sh -c '
    dir=$1
    set -- "$dir"/*/
    [ -d "$1" ] && exit 1
    set -- "$dir"/*
    [ -e "$1" ]' sh {} \; -print

아니면 -links내가 잊어버린 술어를 선택하세요(고마워요 하카타):

find root -type d \
    -links 2 \
    -exec sh -c 'set -- "$1"/*; [ -e "$1" ]' sh {} \; -print

관련 정보