Bash
find 命令在函式內部時拋出錯誤
我可以在 bash 中執行以下命令而不會出現任何錯誤:
$ find /d/Code/Web/Development/Source/ \( -name '*.cs' -o -name '*.cshtml' \) -exec grep -IH UserProfileModel {} \;
我在 .bash_aliases 中寫了一個函式來快速執行這個命令:
search() { local file_type file_types find_cmd opt OPTARG OPTIND or pattern usage usage="Usage: search [OPTION] ... PATTERN [FILE] ... Search for PATTERN in each FILE. Example: search -t c -t h 'hello world' /code/internal/dev/ /code/public/dev/ Output control: -t limit results to files of type" if [[ $1 == --help ]]; then echo "$usage" return fi file_types=() while getopts ":t:" opt; do case $opt in t) file_types+=("$OPTARG") ;; ?) echo "$usage" return ;; esac done shift $((OPTIND-1)) if (( $# == 0 )); then echo "$usage" return fi pattern=$1 shift if (( $# == 0 )); then echo "$usage" return fi find_cmd=(find "$@" '\(') or="" for file_type in "${file_types[@]}"; do find_cmd+=($or -name \'*.$file_type\') or="-o" done find_cmd+=('\)' -exec grep -IH "$pattern" {} '\;') "${find_cmd[@]}" }
但是,該函式會引發錯誤:
find: paths must precede expression
如果我將最後一行更改為
echo "${find_cmd[@]}"
,它將列印與上面完全相同的命令:$ search -t cs -t cshtml UserProfileModel /d/Code/Web/Development/Source/ find /d/Code/Web/Development/Source/ \( -name '*.cs' -o -name '*.cshtml' \) -exec grep -IH UserProfileModel {} \;
我不明白為什麼它在控制台中執行時會起作用,但在函式中執行時會失敗。
另外,如果我將功能簡化為它可以工作的命令:
search() { find /d/Code/Web/Development/Source/ \( -name '*.cs' -o -name '*.cshtml' \) -exec grep -IH UserProfileModel {} \; }
我在 Notepad++ 中編輯 .bash_aliases,但我確保行尾是 Unix 格式。
編輯
根據 F. Hauri 下面的建議,我啟用了調試。顯然這是實際正在執行的命令:
find /d/Code/Web/Development/Source/ '\(' -name ''\''*.cs'\''' -o -name ''\''*.cshtml'\''' '\)' -exec grep -IH UserProfileModel '{}' '\;'
我不確定如何處理這些資訊。在括號之前刪除轉義字元會導致它引發不同的錯誤:
find: missing argument to -exec
提示:執行
set -x
以啟用跟踪模式。Bash 在執行之前列印每個命令。執行set +x
以關閉跟踪模式。+ find . '\(' '\)' -exec grep -IH needle '{}' '\;'
注意最後一個參數
find
是如何\;
代替;
. 左括號和右括號也有同樣的問題。在您的來源中,您已經引用了兩次分號。改變find_cmd=(find "$@" '\(') … find_cmd+=('\)' -exec grep -IH "$pattern" {} '\;')
到
find_cmd=(find "$@" '(') … find_cmd+=(')' -exec grep -IH "$pattern" {} ';')
或者
find_cmd=(find "$@" \() … find_cmd+=(\) -exec grep -IH "$pattern" {} \;)
此外,
-name \'*.$file_type\'
有錯誤的引號 - 您正在尋找名稱以單引號開頭和結尾的文件。做這個-name "*.$file_type"
(*
如果目前目錄中有匹配的文件,則需要引用,並且變數擴展應該用雙引號引起來,除非您知道為什麼需要省略雙引號)。