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
函數作為some-command
主體,就像 Bourne-shell 和大多數類似 Bourne 的 shell 中一樣。() { code } args
作為位置參數運行code
的匿名函數。args
(( $# ))
這裡匿名函數的主體是一個算術表達式,它解析為真的if$#
(參數數量)非零。${param-default}
(來自 Bourne shell)擴展為$param
是否設定了參數或default
其他情況。在這裡${1-$REPLY}
,我們允許直接呼叫我們的函數(如has_subdirs mydir
)或作為如下所示的全域限定符函數。$dir/*(ND/Y1)
$dir
擴展到( )中目錄類型的文件,/
包括隱藏文件 (D
otglob ),如果沒有匹配 (N
ullglob ),也不會出錯。但是對於Y1
,我們停在第一場比賽。因此has_subdirs
,如果目錄至少包含一個子目錄,則匿名函數(因此)將傳回 true。print -rC1
在olumn上列印其參數r
aw1
C
^+has_subdirs
僅限於該has_subdirs
函數未 (^
) 傳回 true 的檔案。
如果必須使用bash
shell,只需執行以下操作:
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
列印未找到的記錄,然後/
在上一筆記錄的開頭。
同樣,要將檔案儲存在 bash 4.4+ 陣列中,您需要透過移動 after-l
或add in 來-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
或在任何 shell 中使用:
find . -type d -links -3
這在目錄連結計數始終為 1 的情況下不起作用btrfs
(在多個 Linux 發行版中已被替換為預設檔案系統),因此我不建議將其作為通用解決方案。ext4
聯合檔案系統與您的情況相同,例如overlayfs
我找到一些合併目錄的連結計數為 1,無論它們是否包含子目錄。
但是,無論在哪裡可用,它都比手動計算子目錄的解決方案具有優勢,即您不需要對目錄進行讀取存取(只需對其父目錄進行搜尋存取)。
答案2
您要尋找的是:
find . -type d -links 2
檔案系統中的每個目錄至少有兩個硬連結 - 父目錄中的目錄本身和“.”入口。子目錄中的每個“..”條目都會在目錄中添加新的硬連結。所以你只需要找到有兩個硬連結的目錄。
另一個答案中建議的命令
find . -type d -links -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
選項就是您想要的。