“find”到“xargs wc”的管道輸出給出了不合理的總數

“find”到“xargs wc”的管道輸出給出了不合理的總數

在一個包含數千個檔案的專案中,我想將總程式碼行數與 PHP 中的程式碼行數進行比較(放棄 CSS、JavaScript 等)。

當我跑步時

find . -type f | xargs wc -l

最後一行的總數是降低比我跑步時

find -E . -regex '.+\.(php|inc)' -type f | xargs wc -l

考慮到第二個find文件清單必須比第一個文件清單(是第一個文件的嚴格子集)更小,在第二種情況下find如何報告更高的總數?wc

答案1

xargs只能透過 ARG_MAX的參數位元組wc

在我的Mac上,ARG_MAX小於整個專案檔案的完整檔案名稱和相對路徑,因此在第一的命令,xargs將結果轉儲findwc 分兩批,這意味著wc推出兩個總計,周圍有數千個文件名。但 ARG_MAX 剛好大於第二 find輸出,因此第二個較小的查找全部顯示在 wc全部的。

解決方法是使用這些命令,這樣我就可以看到所有總計,而無需(無聊的)單一檔案計數行:

find . -type f | xargs wc -l | grep total
find -E . -regex '.+\.(php|inc)' -type f | xargs wc -l | grep total

然後手動將幾個“總”行相加。

答案2

有很多方法可以做到這一點,但xargs不是最好的。這裡有幾個:

  1. 最簡單的是,對cat找到的每個檔案find併計算行數。小心,這只適用於你的檔案名稱沒有空格或奇怪的字元:

    find . -type f | while read n; do cat $n; done | wc -l
    find -E . -regex '.+\.(php|inc)' -type f | while read n; do cat $n; done | wc -l 
    

    如果您的檔案名稱可能包含奇怪的字元(斜線、空格等),請使用以下命令:

    find . -type f | while IFS= read -r n; do cat $n; done | wc -l
    find -E . -regex '.+\.(php|inc)' -type f | while IFS= read -r n; do cat $n; done | wc -l 
    
  2. 更好的方法是使用 find 的-exec選項:

    find . -name "*.pep" -exec cat {} \; | wc
    find -E . -regex '.+\.(php|inc)' -type f -exec cat {} \; | wc
    

答案3

用於對輸出awk的各種「總數」進行求和wc -l

(注意:wc -l傳回換行符的數量,即沒有最終字元的最後「行」將不被計算在內 - 就像或 的\n情況一樣。)awksed

export LC_ALL=C
find . -type f -print0 | xargs -0 wc -l | 
    awk '/^ *[[:digit:]]+ total$/{ total+=$1 }END{print total}'


# xargs alternatives using: find ... -exec <wc|awk|sed> ... '{}' +
#man find | less -p '{} \+'

# wc
find . -type f -exec wc -l '{}' + 2>/dev/null | 
   awk '/^ *[[:digit:]]+ total$/{ total+=$1 }END{print total}'

# awk
find . -type f -exec awk 'END {print NR}' '{}' + 2>/dev/null | 
    awk '{ total+=$1 }END{print total}'

# sed
find . -type f -exec sed -n '$=' '{}' + 2>/dev/null | 
    awk '{ total+=$1 }END{print total}'

相關內容