查找shell内函数

查找shell内函数

我尝试放入find函数内部并使用以下最小工作示例捕获传递给该函数的参数:

功能DO
{
    ls $(find .-type f -name "$@" -exec grep -IHl "TODO" {} \;)
}

但是,当我执行时DO *.tex,我得到“find:路径必须先于表达式:”。但是当我直接这样做时:

ls $(find .-type f -name "*.tex" -exec grep -IHl "TODO" {} \;)

然后我得到所有包含“TODO”的 TeX 文件。

我在DO函数中尝试了很多事情,例如\"$@\",,,'$@'我更改了引号,但行为仍然相同。

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

答案1

您的代码存在一些问题:

  1. 如果该模式与当前目录中的任何文件名匹配,则在调用该函数时该*.tex模式将被扩展。调用该函数时,DO您必须将模式引用为'*.tex',"*.tex"或。\*.tex

  2. 不需要ls。您已经拥有两者find,并且grep能够报告找到的文件的路径名。

  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
}

答案2

您需要将参数引用到函数中,否则 shell 会展开它并且函数会获取文件列表,而不是通配符掩码:

DO "*.tex"

然后您可以使用 just"$1"代替"$@",因为只有一个参数。

相关内容