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-command
fn
Bourne-shell 및 대부분의 Bourne 유사 쉘에서와 같이 함수를some-command
본문으로 정의합니다 .() { code } args
code
익명 함수는 위치 인수로 실행됩니다 .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 -rC1
olumn에 해당 매개변수r
aw를 인쇄합니다.1
C
^+has_subdirs
has_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}'
)
일부 시스템 및 파일 시스템(예: ext4
Linux 기반 시스템)에서는 하위 디렉토리가 있는 디렉토리의 링크 수가 2보다 크다는 사실을 신뢰할 수 있습니다( dir
및 dir/.
각각에 대한 추가 링크 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
옵션이 원하는 것입니다.