2013-03-05 41 views
52

我能夠通過如何統計每個目錄中的文件數量?

find ./ -type d 

列出所有的目錄,我試圖列出每個目錄的內容,並通過使用以下命令

find ./ -type d | xargs ls -l | wc -l 

算在每個目錄的文件數,但此總結通過

find ./ -type d | xargs ls -l 

返回線的總數是有辦法,我可以指望的文件在每個目錄有多少?

+0

您是否正在尋找一種方法來計算直接位於'。/'下的每個子目錄中的文件數? – Tuxdude 2013-03-05 05:25:48

+4

這是一個偏離主題的問題?我希望看到有選票的人有理由評論! **如果這是題外話,那麼這屬於哪裏?**超級用戶?我不這麼認爲。 – 2013-03-05 08:30:42

+4

shell腳本,批處理腳本正在編程範圍內! – 2013-03-05 08:31:42

回答

62

假設你已經GNU發現,讓它找到的目錄,讓慶典做休息:

find . -type d -print0 | while read -d '' -r dir; do 
    files=("$dir"/*) 
    printf "%5d files in directory %s\n" "${#files[@]}" "$dir" 
done 
+1

它只是一個與上述不同的版本,所以:(提示:它按名稱排序並在csv中排序) for find in x。 -maxdepth 1 -type d | sort';做y ='find $ x | wc -l'; echo $ x,$ y;完成 – peteroak 2013-05-11 17:25:55

+2

如果任何文件名都有空格,這將不起作用。 – 2013-05-12 04:07:01

+3

太棒了!把它放到一行(因此它可以直接用在shell中): 'find。 -type d -print0 |同時讀-d''-r dir; do files =(「$ dir」/ *); printf「目錄%s中的%5d文件\ n」「$ {#files [@]}」「$ dir」;完成' – lucaferrario 2013-12-12 23:33:12

1

這應該返回目錄名稱,後面是目錄中文件的數量。

findfiles() { 
    echo "$1" $(find "$1" -maxdepth 1 -type f | wc -l) 
} 

export -f findfiles 

find ./ -type d -exec bash -c 'findfiles "$0"' {} \; 

輸出示例:

./ 6 
./foo 1 
./foo/bar 2 
./foo/bar/bazzz 0 
./foo/bar/baz 4 
./src 4 

export -f因爲find-exec參數不允許,除非你調用bash的明確執行bash的功能是必需的,你需要導出的函數定義當前範圍明確地指向新的shell。

+0

這似乎過分複雜。它也讓我覺得它爲目錄層次結構提供了累計計數,例如'./dir1/dir2/dir3'(統計'dir1'及其子目錄中的文件,而不是計算'dir1/dir2/dir3'與'dir1/dir2'中的文件分開,並且與'/ dir1'中的文件分開)。 – 2013-03-05 05:45:00

+0

我明白這是作者想要的。如果情況並非如此,那麼我同意答案與問題無關。 – Tuxdude 2013-03-05 05:46:33

+0

@JonathanLeffler - 好的,再次閱讀這個問題,我意識到你是對的 - 相應地修改了答案。 – Tuxdude 2013-03-05 05:52:06

10

您能安排找到的所有文件,刪除文件名,讓你對每個文件只包含目錄名的行,再算上次數出現的每個目錄:

find . -type f | 
sed 's%/[^/]*$%%' | 
sort | 
uniq -c 

的如果你有任何包含換行符的文件名或目錄名,這是不太可能的。如果你真的需要擔心文件名或目錄名中的換行符,我建議你找到它們,並修正它們,使它們不包含換行符(並且悄悄地說服他們錯誤的方式)。


如果你有興趣在當前目錄下的每個子目錄中的文件的數量,與眼前的子目錄中的文件一起計數任何子目錄的文件,然後我ð適應sed命令只打印頂級目錄:

find . -type f | 
sed -e 's%^\(\./[^/]*/\).*$%\1%' -e 's%^\.\/[^/]*$%./%' | 
sort | 
uniq -c 

第一種模式捕捉名字,點,斜線,名稱到下一個斜線和斜線的開始,並取代該行只是第一部分,所以:

./dir1/dir2/file1 

./dir1/ 

第二替代捕獲直接在當前目錄中的文件替換;他們最後沒有斜線,並且這些被./取代。然後排序和計數只適用於多個名稱。

+1

這不會輸出不包含任何文件的目錄名稱。不知道這是否是必需的。 – 2013-03-05 05:51:03

+0

確實如此,事實並非如此。 '修復它並不是特別微不足道,因爲即使在'find'的輸出中出現空目錄名也不能保證。有些人可能會:如果有一個文件「dir1/dir2/dir3/file1」,但是「dir1/dir2」只包含子目錄(沒有純文件),那麼你可以推斷它的存在。但是如果'dir1/dir4'沒有文件,它的名字根本不會出現。 – 2013-03-05 06:00:35

+0

非常有用的答案,如果你只是想看到當前目錄的子目錄。 – xixixao 2014-10-21 19:09:39

9

這是一種方法,但可能不是最有效的方法。

find -type d -print0 | xargs -0 -n1 bash -c 'echo -n "$1:"; ls -1 "$1" | wc -l' -- 

給出像這樣的輸出,目錄名稱後跟該目錄中的條目數。請注意,輸出計數還將包含可能不是您想要的目錄條目。

./c/fa/l:0 
./a:4 
./a/c:0 
./a/a:1 
./a/a/b:0 
+0

對於'find'找到的每個目錄運行3個命令('bash','ls','wc')似乎非常昂貴。 – 2013-03-05 05:43:36

+0

@JonathanLeffler同意,因此我的答案的第一行。你的解決方案更好。 – 2013-03-05 05:47:45

+0

很酷這就是我要找的 我可以問最後是' - '嗎? – once 2016-03-21 02:58:13

1

我在這裏住這一點,未來的提醒

ls |parallel 'echo {} && ls {}|wc -l' 
+0

我的外殼將文件夾着色。我使用'ls --color = never |並行'echo -n {} && ls {} | wc -l'' – 2017-09-20 02:06:07

54

這版畫每個目錄的當前目錄級別的文件數量:

du -a | cut -d/ -f2 | sort | uniq -c | sort -nr 
+3

如果想要遞歸地列出頂級目錄中的文件數量,那麼迄今爲止最好的(也是最優雅的)解決方案。 – itoctopus 2017-04-29 13:41:12

+3

這有兩個問題:它比每個目錄的實際數量多一個文件,並且它將包含當前目錄大小的無用行作爲「1 _size_」。兩者都可以用'du -a |修復sed'/.*\.\/.*\/.*/!d'|剪下-d/-f2 |排序| uniq -c'。添加'| sort -nr'按計數而不是目錄名稱進行排序。 – dessert 2017-08-04 11:57:05

4

其他人的解決方案有一個缺點或另一個缺點。

find -type d -readable -exec sh -c 'printf "%s " "$1"; ls -1UA "$1" | wc -l' sh {} ';' 

說明:

  • -type d:我們感興趣的目錄。
  • -readable:我們只希望他們,如果它是可能列出其中的文件。請注意,當find嘗試在其中搜索更多目錄時仍然會發出錯誤,但這樣可以防止爲它們調用-exec
  • -exec sh -c BLAH sh {} ';':對於每個目錄,運行此腳本片段,其中$0設置爲sh$1設置爲文件名。
  • printf "%s " "$1":可移植且最低限度地打印目錄名稱,後面只有一個空格,而不是換行符。
  • ls -1UA:列出文件,每行一個,在目錄順序(避免失速管),但不包括只有特殊目錄...
  • wc -l:算上線
+0

修改顯示文件首先計算在行上,並按它們排序:'find -type d -readable -exec sh -c'ls -1UA「$ 1」| wc -l | tr -d「\ n」; printf「\ t%s \ n」「$ 1」'sh {}';' | sort -n' – 2017-11-22 15:27:01

0

發現。 -type f -printf'%h \ n'|排序| uniq的-c

給出了例子:

5 . 
    4 ./aln 
    5 ./aln/iq 
    4 ./bs 
    4 ./ft 
    6 ./hot 
2

這也與遍歷LS,而不是找

for f in */; do echo "$f -> $(ls $f | wc -l)"; done

說明來完成:

for f in */; - 循環遍歷所有目錄

do echo "$f -> - 打印出每個目錄名

$(ls $f | wc -l) - 調用此目錄爲LS和計算行

+0

如果目錄名稱包含空格,則這不起作用。 – Xylol 2017-10-05 14:45:05

0

我試着用這裏的一些人,但結束了與包含在文件計數的子文件夾時,我只希望這些文件。這會爲當前文件夾中的每個子文件夾打印./folder/path<tab>nnn以及不包括子文件夾的文件數量。

for d in `find . -type d -print` 
do 
    echo -e "$d\t$(find $d -maxdepth 1 -type f -print | wc -l)" 
done 
相關問題