리눅스 찾기-type d: ./dir1 없이 ./dir1/dir2와 같은 가장 깊은 디렉토리를 나열하는 방법은 무엇입니까?

리눅스 찾기-type d: ./dir1 없이 ./dir1/dir2와 같은 가장 깊은 디렉토리를 나열하는 방법은 무엇입니까?
find . -type d

일반적으로 표시됩니다.

./dir1
./dir1/dir2
./dir3
./dir3/dir4
./dir3/dir4/dir5
...

나는 그저 원할 뿐이야

./dir1/dir2
./dir3/dir4/dir5

, 상위 ./dir1,...이 없습니다.

즉, 하위 디렉터리가 없는 디렉터리만 보고 싶습니다.

어떤 아이디어가 있나요?

-links 2편집: 일반적인 Linux 환경에서 작동하는 것으로 나타났습니다 .

docker run -it --rm ubuntu:bionic find /etc -type d -links 2

완벽하게 작동합니다.

그러나 디렉터리(MacOS 또는 Windows)를 Docker 컨테이너에 탑재하면 상황이 바뀌고 작동하지 않습니다. 다음을 시도해 볼 수 있습니다.

docker run -it --rm -v /etc:/etc_of_host ubuntu:bionic find /etc_of_host -type d -links 2

답변1

그리고 zsh:

has_subdirs() () (( $# )) ${1-$REPLY}/*(ND/Y1)
print -rC1 -- **/*(ND/^+has_subdirs)

또는 중개 기능 없이 직접:

print -rC1 -- **/*(ND/^e['()(($#)) $REPLY/*(ND/Y1)'])

그건:

  • fn() some-commandfnBourne-shell 및 대부분의 Bourne 유사 쉘에서와 같이 함수를 some-command본문으로 정의합니다 .
  • () { code } argscode익명 함수는 위치 인수로 실행됩니다 .args
  • (( $# ))여기서 익명 함수의 본문은 다음을 해결하는 산술 표현식입니다.진짜$#(매개변수 수)가 0이 아닌 경우 .
  • ${param-default}(Bourne 쉘에서) $param인수가 설정되었는지 default여부로 확장됩니다. 여기서는 ${1-$REPLY}함수를 직접 호출 has_subdirs mydir하거나(예: ) 아래와 같이 전역 한정자 함수로 호출할 수 있습니다.
  • $dir/*(ND/Y1)$dir/숨겨진 파일( otglob )을 포함하여 ( )에 있는 디렉터리 유형의 파일로 확장하고 , D일치하는 항목이 없어도( ullglob ) N오류를 발생시키지 않습니다 . 하지만 의 경우 Y1첫 번째 게임에서 멈췄습니다. 따라서 has_subdirs익명 함수는 디렉터리에 하위 디렉터리가 하나 이상 포함되어 있으면 true를 반환합니다.
  • print -rC1olumn에 해당 매개변수 raw를 인쇄합니다.1 C
  • ^+has_subdirshas_subdirs이 함수가 true를 반환하지 않는( ) 파일에만 해당됩니다 ^.

bash쉘을 사용해야 한다면 다음을 수행하십시오.

zsh << 'EOF'
  print -rC1 -- **/*(ND/^e['()(($#)) $REPLY/*(ND/Y1)'])
EOF

또는 결과를 bash 배열에 저장합니다(bash-4.4+ 필요).

readarray -td '' array < <(zsh << 'EOF'
  print -rNC1 -- **/*(ND/^e['()(($#)) $REPLY/*(ND/Y1)'])
EOF
)

(임의의 경로를 저장할 수 있으려면 NUL로 구분된 레코드를 사용하십시오.)

그렇지 않은 경우 zsh다음 perl을 수행할 수 있습니다.

find . -depth -type d -print0 |
  perl -l -0ne 'print if rindex $prev, "$_/", 0; $prev = $_'

또는 GNU가 있는 경우 awk:

find . -depth -type d -print0 |
  gawk -v 'RS=\0' 'index(prev, $0"/") != 1; {prev = $0}'

find인쇄 된 목차깊이 우선(해당 분기 이전에 나가기) 찾을 수 없는 레코드를 가져오거나 인쇄한 다음 perl이전 레코드의 시작 부분에 표시합니다.awk/

-l마찬가지로, bash 4.4+ 배열에 파일을 저장하려면 다음으로 이동하거나 다음을 추가하여 -0출력에서 ​​NUL로 구분된 레코드로 전환 해야 합니다 .perl-v 'ORS=\0'gawk

readarray -td array < <(
  find . -depth -type d -print0 |
    perl -0lne 'print if rindex $prev, "$_/", 0; $prev = $_'
)
readarray -td array < <(
  find . -depth -type d -print0 |
    gawk -v 'RS=\0' -v 'ORS=\0' 'index(prev, $0"/") != 1; {prev = $0}'
)

일부 시스템 및 파일 시스템(예: ext4Linux 기반 시스템)에서는 하위 디렉토리가 있는 디렉토리의 링크 수가 2보다 크다는 사실을 신뢰할 수 있습니다( dirdir/.각각에 대한 추가 링크 dir/subdir/..).

print -rC1 -- **/*(ND/l-3)

find또는 모든 쉘에서 사용하십시오.

find . -type d -links -3

디렉터리의 링크 수가 항상 1 btrfs(여러 Linux 배포판에서 기본 파일 시스템으로 대체됨)인 경우에는 작동하지 않으므로 일반 솔루션으로 권장하지 않습니다.ext4

유니온 파일 시스템은 귀하의 경우와 동일합니다. 예를 들어 overlayfs일부를 찾았습니다.병합디렉터리에는 하위 디렉터리가 포함되어 있는지 여부에 관계없이 링크 수가 1개입니다.

그러나 가능한 경우 디렉터리에 대한 읽기 액세스 권한이 필요하지 않은 하위 디렉터리를 수동으로 계산하는 솔루션에 비해 이점이 있습니다(상위 디렉터리에 대한 검색 액세스만 가능).

답변2

당신이 찾고 있는 것은:

find . -type d -links 2

파일 시스템의 모든 디렉토리에는 최소한 두 개의 하드 링크(상위 디렉토리의 디렉토리 자체와 "." 항목)가 있습니다. 하위 디렉토리의 각 ".." 항목은 디렉토리에 새로운 하드 링크를 추가합니다. 따라서 두 개의 하드 링크가 있는 디렉토리를 찾으면 됩니다.

다른 답변에서 제안된 명령

find . -type d -links -3

동일한 작업을 수행하되 "하드 링크된 디렉터리가 3개 미만"이라고 명시합니다.

답변3

가장 많이 정렬된 항목:

p="";(find . -type d;echo) | while read d; do [[ $p && $d != $p/* ]] && echo $p; p=$d; done

연속해서

a="";(find . -type d;echo )|while read i; do if  [[ (! $i =~ $a) && ("$a" != "") ]]; then echo $a; fi; a=$i;done

OP에서 언급했듯이 :

a="";(find . -type d;echo )|while read i; do [[ $i != $a/* && ! -z "$a" ]] && echo $a; a=$i;done

답변4

읽다 man find. 이 -mindepth옵션이 원하는 것입니다.

관련 정보