Bash
在 shell 函式中查找
我嘗試放入
find
函式內部並使用以下最小工作範例擷取傳遞給該函式的參數:功能 DO { ls $(find . -type f -name "$@" -exec grep -IHl "TODO" {} \;) }
但是,當我執行時
DO *.tex
,我得到“查找:路徑必須在表達式之前:”。但是當我直接這樣做時:ls $(find . -type f -name "*.tex" -exec grep -IHl "TODO" {} \;)
然後我得到所有包含“TODO”的TeX文件。
我在函式中嘗試了很多東西
DO
,例如\"$@\"
,'$@'
,我更改了引號,但行為仍然相同。那麼,如何強制在函式內部找到工作?
您的程式碼中有幾個問題:
- 如果模式與目前目錄中的任何文件名匹配,則
*.tex
在呼叫函式時將擴展模式。DO
您必須將模式引用為'*.tex'
,"*.tex"
或者\*.tex
在呼叫函式時引用。ls
不需要。您已經擁有兩者find
,grep
並且能夠報告找到的文件的路徑名。-name "$@"
只有在"$@"
包含單個項目時才能正常工作。使用會更好-name "$1"
。有關允許多種模式的解決方案,請參見下文。函式可以寫成
DO () { # Allow for multiple patterns to be passed, # construct the appropriate find expression from all passed patterns for pattern do set -- "$@" '-o' '-name' "$pattern" shift done # There's now a -o too many at the start of "$@", remove it shift find . -type f '(' "$@" ')' -exec grep -qF 'TODO' {} ';' -print }
像這樣呼叫這個函式
DO '*.tex' '*.txt' '*.c'
將使其執行
find . -type f '(' -name '*.tex' -o -name '*.txt' -o -name '*.c' ')' -exec grep -qF TODO {} ';' -print
如果文件包含字元串,這將生成具有這些文件名後綴的文件的路徑名列表
TODO
。要使用
grep
而不是find
列印找到的路徑名,請將-exec ... -print
位更改為-exec grep -lF 'TODO' {} +
. 這將更有效率,特別是如果您有大量與給定表達式匹配的文件名。無論哪種情況,您都絕對不需要使用ls
.允許使用者使用
DO tex txt c
您的功能可以更改為
DO () { # Allow for multiple patterns to be passed, # construct the appropriate find expression from all passed patterns for suffix do set -- "$@" '-o' '-name' "*.$suffix" # only this line (and the previous) changed shift done # There's now a -o too many at the start of "$@", remove it shift find . -type f '(' "$@" ')' -exec grep -qF 'TODO' {} ';' -print }