Command-Line

使用 find 命令查找行數

  • April 17, 2018

考慮在https://cloud.r-project.org/src/base/R-3/R-3.4.4.tar.gz找到的 R 原始碼儲存庫。我將儲存庫解壓縮到一個文件夾中。現在,我想知道目錄中有多少行。所以,我嘗試了以下命令:

find . -type f -exec wc -l {} \+

產生 394968 但如果我嘗試以下命令:

find . -type f -exec cat {} \+ | wc -l

它產生1848857!

為什麼這兩個看似相似的find命令操作會產生如此截然不同的結果?而且,查找行數的正確方法是什麼,最好使用命令行實用程序而不是編寫一個小工具的腳本?

您提到的第一個命令find . -type f -exec wc -l {} +,實際上是說“wc -l在盡可能多的文件上執行,直到所有文件都被處理”。這可以執行wc多次!

另一方面,find . -type f -exec cat {} + | wc -l可以執行 cat多次,但只會執行wc一次。(更詳細地說,這是因為在這種情況下cat由 呼叫find,它可以並且確實決定執行它多次,而管道字元之後的部分wc -l,超出了 的範圍find,因此由您的殼,只有一次。)

您說第一個命令“產生 394968”,但實際上沒有;在我的系統上,它的輸出以:

(Many more lines elided...)
    23 ./po/Makefile.win
    64 ./po/README
     1 ./VERSION-NICK
    97 ./README
258450 total

然而,通過添加grep total,可以看到它wc確實執行了兩次:

$ find . -type f -exec wc -l {} + | grep total
1590407 total
258450 total

而且,實際上,1590407 加上 258450 是 1848857,這與第二個命令一致。


find 手冊頁模糊地暗示了為什麼在命令版本中wc多次執行的解釋:find -exec wc +

-exec *command* {} +

-exec操作變體在選定文件上執行指定命令,但命令行是通過在末尾附加每個選定文件名來建構的;該命令的呼叫總數將遠少於匹配文件的數量。命令行的建構方式與xargs建構其命令行的方式大致相同。

請注意這是如何說“比……少得多”而不是“只有一次”。xargs的 文件提示,--max-chars如果使用者未設置,則會自動設置其選項:

--max-chars=*max-chars*

-s *max-chars*

每個命令行最多使用*max-chars*字元,包括命令和初始參數以及參數字元串末尾的終止空值。最大允許值取決於系統,計算為 exec 的參數長度限制,減去環境的大小,減去 2048 字節的空間。如果此值大於 128KiB,則使用 128Kib 作為預設值;否則,預設值為最大值。

這限制了一次呼叫可以傳遞多少個文件名wc,解釋了為什麼對於大量文件,wc會發生多次呼叫,每個呼叫都在輸入的一個分區上操作。

引用自:https://unix.stackexchange.com/questions/438160