在 shell 函数中查找

fau*_*uve 1 bash alias function arguments

我尝试放入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函数中尝试了很多东西,例如\"$@\", '$@',我更改了引号,但行为仍然相同。

那么,如何强制在函数内查找工作呢?

Kus*_*nda 5

您的代码中有几个问题:

  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
}
Run Code Online (Sandbox Code Playgroud)

像这样调用这个函数

DO '*.tex' '*.txt' '*.c'
Run Code Online (Sandbox Code Playgroud)

将使它执行

find . -type f '(' -name '*.tex' -o -name '*.txt' -o -name '*.c' ')' -exec grep -qF TODO {} ';' -print
Run Code Online (Sandbox Code Playgroud)

如果文件包含字符串TODO.

要使用grep而不是find打印找到的路径名,请将-exec ... -print位更改为-exec grep -lF 'TODO' {} +. 这将更有效率,尤其是当您有大量文件名与给定的表达式匹配时。在任何一种情况下,您绝对不需要使用ls.


允许用户使用

DO tex txt c
Run Code Online (Sandbox Code Playgroud)

你的功能可以改成

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
}
Run Code Online (Sandbox Code Playgroud)