Bash

在 shell 函式中查找

  • November 25, 2018

我嘗試放入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,例如\"$@\", '$@',我更改了引號,但行為仍然相同。

那麼,如何強制在函式內部找到工作?

您的程式碼中有幾個問題:

  1. 如果模式與目前目錄中的任何文件名匹配,則*.tex在呼叫函式時將擴展模式。DO您必須將模式引用為'*.tex'"*.tex"或者\*.tex在呼叫函式時引用。
  2. ls不需要。您已經擁有兩者findgrep並且能夠報告找到的文件的路徑名。
  3. -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
}

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