Linux find <DOCKER_MOUNTED_DIR> -type d:如何列出最深的目錄,例如./dir1/dir2沒有./dir1?
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
與
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-like shell 中一樣。() { code } args
作為位置參數執行的匿名函式code
。args
(( $# ))
此處,該匿名函式的主體是一個算術表達式,如果(參數的數量)非零,則該表達式解析為真。$#
${param-default}
(來自 Bourne shell)擴展為$param
是否設置了參數default
。在這裡${1-$REPLY}
,我們允許我們的函式被直接呼叫(ashas_subdirs mydir
)或作為一個萬用字元函式,如下所示。$dir/*(ND/Y1)
擴展為$dir
(/
) 中目錄類型的文件,包括隱藏文件 (D
otglob),如果沒有匹配項 (ullglob),則不會出錯N
。但是Y1
,我們在第一場比賽中停止。has_subdirs
因此,如果目錄包含至少一個子目錄,匿名函式(因此)將返回 true。print -rC1
在olumn上列印其參數r
aw1
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
以列印未找到的記錄,然後/
在上一條記錄的開頭列印。同樣,要將文件儲存在 bash 4.4+ 數組中,您需要通過將
-l
after-0
inperl
或 add-v 'ORS=\0'
in切換到輸出上的 NUL 分隔記錄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
這將不起作用
btrfs
(在幾個 Linux 發行版中已被替換ext4
為預設文件系統),例如目錄的連結計數始終為 1,因此我不建議將其作為一般解決方案。與您的情況相同的聯合文件系統,例如
overlayfs
我發現一些合併目錄的連結計數為 1,無論它們是否包含子目錄。但是,無論它在哪裡可用,if 都比手動計算不需要對目錄的讀取訪問權限的子目錄的解決方案具有優勢(僅搜尋對其父目錄的訪問權限)。
你要找的是:
find . -type d -links 2
文件系統中的每個目錄至少有兩個硬連結——父目錄中的目錄本身和“.”。入口。子目錄中的每個“..”條目都會為目錄添加一個新的硬連結。所以你只需要找到有兩個硬連結的目錄。
另一個答案中建議的命令
find . -type d -links -3
做同樣的事情,但聲明“目錄少於三個硬連結”。