帶有通配符的 find -exec

帶有通配符的 find -exec

我正在嘗試使用 bash“查找”來處理包含 .log 文件的所有資料夾並獲取其大小。然而,通配符沒有按預期工作。這不會返回任何內容:

find . -type d -exec test -e '{}/*.log' \; -exec du -d0 '{}' \;

但是,如果我替換*.logfoo.log,那麼它對於包含該檔案名稱的目錄將按預期工作。

基於一些類似的 SE 帖子,我嘗試過:

find . -type d -exec bash -c 'test -e "{}/*.log"' \; -exec du -d0 '{}' \;
find . -type d -exec bash -c 'test -e "$1/*.log"' '{}' \; -exec du -d0 '{}' \;

但這些並沒有更好的效果。

答案1

find … -exec test -e '{}/*.log'你傳遞一個像something/*.logto 這樣的字串時test,哪裡*文字。這兩個工具都不將其視為通配符。如果它是參數的一部分(而不是整個參數),則某些實作find甚至不會擴展。{}{}

您稍後的嘗試之一會嵌入{}shell 程式碼中。切勿嵌入{}shell 程式碼中。在這個問題上,另一種嘗試更好,你已經接近解決方案了。這會有點工作:

# still flawed though
find . -type d -exec bash -c 'test -e "$1/"*.log' bash '{}' \; -exec du -d0 '{}' \;

中的第二個 sh 是什麼sh -c 'some shell code' sh。然而,主要的「修復」是不在 shell 程式碼中引用星號。這樣,它在內殼中是一個通配符(但在外殼中不是,它在那裡被正確地單引號引用)。問題是*.log可能會擴展到多個單字(如果有許多匹配檔案),這種情況會破壞test呼叫。

以下程式碼將尋找包含*.log檔案的目錄:

find . -type d -exec sh -c '
   for f in "$1/"*.log; do test -e "$f" && exit 0; done; exit 1
' sh {} \; -print

該代碼是可移植的。不需要inner bashsh應該更快。如果您願意,請替換-print為。-exec du …

exit 0其工作原理是,一旦test確認某些匹配文件的存在,就從內殼返回成功( )。尚未測試的配對文件(如果有)不會被白白測試,這樣可以節省時間。如果沒有匹配,則模式將保持原義,test將失敗,整個 shell 將因失敗而退出 ( exit 1)。請記住-exec,這也是一個測試,因此它會影響是否執行-print(或您放在那裡的任何內容)。-exec du …


另一種方法可能是讓find自己找到匹配的文件

find . -name '*.log' … -print

並解析其輸出以隔離目錄名稱,最後xargsdu.目錄可能會出現多次,路徑名中的換行符將需要不可移植的程式碼(從 開始-print0)。我認為這會變得不必要的複雜。找目錄似乎更勝一籌。


¹ 註釋test -e會告訴您是否有文件這可能是目錄或其他什麼。若要確認常規文件的存在,請使用test -f.

答案2

尋找/掃描日誌檔案然後收集唯一的目錄名稱會更容易。

find命令應該提取目錄,添加uniq以刪除重複項。-z/標誌-0有助於確保帶有換行符/空格/引號的路徑名被完美解析:

find . -type f -name \*.log -exec dirname -z {} \+ | uniq -z | xargs -0 -r du -d0

| sort -rn |head如果搜尋最大的磁碟使用量,請新增。

相關內容