2009-10-15 39 views
13

有沒有一種簡單的方法可以在Linux中只列出給定目錄下的目錄? 爲了更好地解釋,我可以這樣做:在Linux中列出所有的葉子目錄

find mydir -type d 

這給:

mydir/src 
mydir/src/main 
mydir/bin 
mydir/bin/classes 

我想的卻是:

mydir/src/main 
mydir/bin/classes 

我可以在遍歷一個bash腳本做到這一點線和刪除前一行,如果下一行包含路徑,但我想知道是否有一個更簡單的方法,不使用bash循環。

+0

你的榜樣,'找到mydir的-mindepth 2 - 類型d'可以工作,但是當你有多個最大深度時它不會。你是否真的只想列出不包含其他目錄的目錄,或者你是否希望看到特定級別的目錄結構? – Cascabel 2009-10-15 19:17:54

+0

是的,謝謝澄清 - 我的例子是一個簡單的例子。我的確在尋求更爲一般的解決方案。 此外,我期待看到一般的目錄結構,並不真正關心目錄中的文件(所以葉也就意味着在這個上下文中的「葉目錄」)。謝謝。 – amol 2009-10-15 21:09:38

回答

10
find . -type d | sort | awk '$0 !~ last "/" {print last} {last=$0} END {print last}' 
+0

謝謝,只是我尋找的解決方案:) – amol 2009-10-15 21:02:11

+0

這將產生正確的,但未排序的結果,而不'排序'(所以你可以把它放在最後,而不是,如果你想)。 – 2009-10-16 05:16:57

+0

如果您有兩個目錄:foo/bar和foo/bar_baz,則這不起作用。 foo/bar不會被打印。 – mattismyname 2012-08-07 19:43:45

4

我想不出沒有循環的任何事情。所以,這裏有一些循環:

顯示當前目錄下的葉目錄,無論其深度:

for dir in $(find -depth -type d); do [[ ! $prev =~ $dir ]] && echo "$dir" ; prev="$dir"; done 

這個版本正確處理目錄名稱包含空格:

saveIFS=$IFS; IFS=$'\n'; for dir in $(find -depth -type d); do [[ ! $prev =~ $dir ]] && echo "${dir}" ; prev="$dir"; done; IFS=$saveIFS 

這裏是一款使用Jefromi的建議:

find -depth -type d | while read dir; do [[ ! $prev =~ $dir ]] && echo "${dir}" ; prev="$dir"; done 
+0

OP詢問是否有比循環輸出更簡單的方法,而不是如何編寫循環。也就是說,使用'find .... |也是一個好主意而在$(...)'中讀取dir而不是'dir',因爲它不必在打印任何內容之前完成整個查找。 – Cascabel 2009-10-15 19:29:53

+0

@Jefromi:將'find'換成'while'也可以免費處理空格。 – 2009-10-15 19:46:34

+0

那麼,避免循環顯然不是一個難的「要求」,但我希望有一個更簡單+直觀的方式來做到沒有循環。感謝您的查找|雖然信息。 – amol 2009-10-15 21:01:40

0

這仍然是一個循環,因爲它在sed使用分支命令:

find -depth -type d |sed 'h; :b; $b; N; /^\(.*\)\/.*\n\1$/ { g; bb }; $ {x; b}; P; D' 

基於在info sed(uniq的工作一樣)的腳本。

編輯這裏是sed腳本註釋爆發(從info sed複製和修改):

# copy the pattern space to the hold space 
h 

# label for branch (goto) command 
:b 
# on the last line ($) goto the end of 
# the script (b with no label), print and exit 
$b 
# append the next line to the pattern space (it now contains line1\nline2 
N 
# if the pattern space matches line1 with the last slash and whatever comes after 
# it followed by a newline followed by a copy of the part before the last slash 
# in other words line2 is different from line one with the last dir removed 
# see below for the regex 
/^\(.*\)\/.*\n\1$/ { 
    # Undo the effect of 
    # the n command by copying the hold space back to the pattern space 
    g 
    # branch to label b (so now line2 is playing the role of line1 
    bb 
} 
# If the `N' command had added the last line, print and exit 
# (if this is the last line then swap the hold space and pattern space 
# and goto the end (b without a label) 
$ { x; b } 

# The lines are different; print the first and go 
# back working on the second. 
# print up to the first newline of the pattern space 
P 
# delete up to the first newline in the pattern space, the remainder, if any, 
# will become line1, go to the top of the loop 
D 

這裏是正則表達式是這樣做的:

  • / - 啓動模式
  • ^ - 匹配行首
  • \( - 啓動捕獲組(返回參考子表達式)
  • .* - 零個或多個(*)任意字符(。)
  • \) - 端捕獲組
  • \/ - 一斜槓(/)(其中\轉義)
  • .* - 零個或多個任意字符
  • \n - 一個新行
  • \1 - 副本(在這種情況下,無論是在行的開頭和最後一個斜槓之間)
  • $ - 匹配行尾
  • / - 結束模式
+0

您的建議工作得很好,但我覺得很難理解。不過謝謝,我會試着弄清楚sed選項的含義。 – amol 2009-10-15 21:05:12

0

我覺得你可以看看所有的目錄,然後重定向輸出中,並使用xargs的計數數量文件每個子目錄,當沒有子目錄(xargs的發現SUBDIR型d | wc -l ...類似的東西,我現在無法測試)你找到了一片葉子。

雖然這仍然是一個循環。

+0

嗯..也許我沒有解釋什麼「葉子」意思是非常正確的,我的意思是「葉子尖」,所以如果所有的目錄都是文件,它仍然可以作爲我的問題的一個「葉子」。 – amol 2009-10-15 20:57:41

+0

ouhla, m累了,我你在尋找目錄下和wc -l == 0,那應該是訣竅...... – LB40 2009-10-15 20:59:47

4

如果你正在尋找可視化的東西,tree -d是不錯的。

 
drinks 
|-- coke 
| |-- cherry 
| `-- diet 
|  |-- caffeine-free 
|  `-- cherry 
|-- juice 
| `-- orange 
|  `-- homestyle 
|   `-- quart 
`-- pepsi 
    |-- clear 
    `-- diet 
+0

謝謝,這也很有用(不是爲我目前的問題,但很高興知道) 我想知道,樹是最近添加?我記得大約一年前需要類似這樣的東西(當時在RHEL上,現在在Ubuntu上),最後在http://centerkey.com/tree上使用腳本。 – amol 2009-10-16 20:33:03

10

如果你想只有葉目錄(不包含任何子目錄目錄),看看this other question。答案也explains it,但總之它是:

find . -type d -links 2 
+1

至少在Mac上,鏈接包括當前,父目錄和子目錄以及文件。所以這個解決方案只適用於空葉子目錄。 – 2012-03-02 13:46:03

+0

我剛剛注意到它在SMB掛載上也不起作用。但它在NFS掛載上。但是在工作的地方(本地或NFS Linux目錄),它肯定是最簡單的解決方案。 – mivk 2012-04-08 17:17:30

0

試試下面的一行代碼(在Linux & OS X測試):

find . -type d -execdir sh -c 'test -z "$(find "{}" -mindepth 1 -type d)" && echo $PWD/{}' \; 
相關問題