Bash

管道查找輸出時如何處理奇怪的路徑字元?

  • April 28, 2022

我有一個問題,我想從find命令中找到每條路徑的長度。我的第一次嘗試是執行這樣的東西:

find . -exec sh -c "echo {} | wc -c" \;

我從這個答案中得到了這個想法。(上面的命令不是我的問題,我只是用它作為一個例子,它完全是人為的。另外,有時我可能需要多個管道。)

但是當我執行它時,輸出中有錯誤,可能是由於輸出路徑中的特殊字元。不幸的是,我不知道哪些路徑導致了問題,並且錯誤消息沒有提供資訊。不管…

我後來偶然發現了這個答案

find命令直接執行命令。該命令(包括文件名參數)不會被 shell 或任何其他可能修改文件名的東西處理。這是非常安全的。

這似乎很方便。事實上,如此方便,以至於-exec sh -c ...“治愈”似乎比疾病更糟糕。

所以我的問題是,當我需要使用管道命令find並且我的路徑可能包含特殊字元時,我該怎麼辦?這個問題是否有一個通用的解決方案,我不必考慮一堆警告?我正在使用 bash。


注意:這是一個類似的問題:如何最好地將 find + exec 命令的輸出發送到管道?不同之處在於,我不一定要嘗試將輸出輸出到-exec. 即,如果find ... -exec ... foo {} | bar \;是要走的路,那對我來說很好。我只是在尋找阻力最小的通用路徑,命令的結構對我來說並不重要。

將文件名作為參數傳遞給 shell 腳本:

find . -exec sh -c 'printf "%s\n" "$1" | wc -c' sh {} \;

或者對於每個 shell 呼叫的多個文件:

find . -exec sh -c 'for x in "$@"; do printf "%s\n" "$x" | wc -c; done' sh {} +

你的命令

find . -exec sh -c "echo {} | wc -c" \;

將在 shell 命令行上按原樣插入文件名。它僅適用於不包含空格或 shell 特殊字元的文件名。例如,類似 a 的東西Don't stop me now.mp3this&that.txt導致問題。(第一個會產生一個未終止的帶引號的字元串,第二個會echo在後台開始,然後嘗試執行一個名為that.txt.)

另一方面,sh -c ... sh {} \;(或... {} +已將find文件名作為不同的參數傳遞給 shell,然後它們將在位置參數中可用,並且可以在不與 shell 語法混合的情況下使用它們。("$1"對於第一個,"$@"對於整個列表。記住引號。)

對於檢查文件名長度的情況,您也可以"${#var}"在 shell 中獲取它,除了它根據目前語言環境給出字元wc -c長度,同時計算字節數。

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