执行 find 调用的命令

执行 find 调用的命令

有没有办法递归调用find?

我想仅在与另一个模式匹配的目录中搜索与给定模式匹配的文件。

基本上:

for each (sub)directory D matching "*.data"
do
  for each file F in directory D (with subdirs) matching "*.important.txt"
  do
    run command foo on F
  done
done

现在,如果我忽略最内在的要求(在 F 中运行命令 foo),这很简单:

find . -type d -name "*.data" \
     -exec find \{\} -type f -name "*.important.txt" \;

但是,我还没有找到将命令传递到内部的方法find。例如打印出以下内容查找:缺少“-exec”参数每次调用内部查找时:

 find . -type d -name "*.data" \
      -exec find \{\} -type f -name "*.important.txt" \
                 -exec "foo \{\} \;" \;

任何解决方案都应该符合 posix 标准(可在/bin/sh脚本中运行),尤其是。我不是在寻找解决方案

  • 将内部查找包装到单独的 shell 脚本中
  • 将内部查找包装到 bash 函数中

答案1

要运行find它自己的结果,您可以使用(或)-c的参数来防止外部 find 命令特殊对待内部。但是,您随后需要将外部查找的结果作为参数传递给,可以使用 进行扩展:shbash{}sh$0

find . -type d -name "*.data" \
      -exec sh -c 'find "$0" -type f -name "*.important.txt" -exec echo \{\} \;' \{\} \;

注意:$0应加引号 ( "$0") 以防止目录名称包含空格的问题。

这并不是真正的“递归”解决方案,因为它不允许在没有一些毛茸茸的转义的情况下任意深度嵌套,但它确实支持find -exec您在示例中要求的两个级别 s 。

如果您的示例与实际问题类似,您也可以尝试使用参数-path来查找:

find . -path '*.data/*important.txt'

答案2

bash 版本(不兼容 POSIX)

#!/bin/bash
find . -type d -name 'a *' -print0 \
    | while IFS= read -r -d '' dir ; do
        find "$dir" -type f -name "*.c" -exec echo \{\} \;
    done

问题:


(坏)sh 版本(符合 POSIX)

#!/bin/sh
# WARNING: while this will work on directory names with spaces,
#          it will break on directory names that contain newlines
find . -type d -name 'a *' -print \
    | while IFS= read -r dir ; do
        find "$dir" -type f -name "*.c" -exec echo \{\} \;
    done

问题:如评论中所述,它将在包含换行符的目录名称上中断。您可能认为这不是一个现实的问题,但这会给您的脚本增加不必要的脆弱性。也许另一个程序有一个错误,会创建这样的目录等。


(更好)sh版本

伊恩·罗伯逊的回答


顺便提一句。如果您需要脚本兼容 POSIX,那么使用shellcheck。例如,它会注意到read -dPOSIX 中没有定义。

相关内容