查找:带有条件的多个“-exec”

查找:带有条件的多个“-exec”

我正在尝试将标准 C 包包含stdint.h到包含单词 的文件中LARGE_INTEGER,作为从 Windows 到 Linux 驱动程序转换的一部分,如所讨论的这里对于数据类型。我知道之前关于 find 和 xargs 的线程,这里这里

GNU find部分的代码主要是基于这个线:

gfind /tmp/ -type f                                                      \
    \( -name "*.h" -o -name "*.cpp" \)                                   \
    -exec ggrep -Pl "LARGE_INTEGER" {} +

及其伪代码扩展名,我还希望文件必须包含单词LARGE_INTEGER

gfind /tmp/ -type f                                                \
    \( -name "*.h" -o -name "*.cpp" \)                             \
    -and -exec ggrep -Pl "LARGE_INTEGER" {} \;                     \
    | xargs gsed -i '1s/^/#include <stdint.h>\n/'

我不确定-and并给予的地方

gsed: can't read /tmp/: No such file or directory
...

我按照 commandlinefu 中的示例进行操作这里

如何将新命令组合到基于 GNU SED 的查找中?

答案1

我将1 find与两个-exec操作一起使用,例如:

寻找 。 -type f -exec grep -qFSOME_STRING{} \; -执行sed'命令' {} \;

仅当第一个命令的计算结果为时,第二个命令才会运行真的IE退出代码 0sosed仅当文件包含时才会处理有问题的文件SOME_STRING。很容易看出它是如何工作的:

寻找 。 -type f -exec grep -qFSOME_STRING{} \; -打印

它应该只列出包含以下内容的文件SOME_STRING。当然,您始终可以链接两个以上的表达式,也可以使用!(否定)等运算符,例如:

寻找 。 -type f -exec grep -qF{} \; ! -exec grep -qF{} \; -打印

将仅列出包含以下内容的文件但不包含
无论如何,就你的情况而言:

gfind /tmp/ -type f \( -name "*.h" -o -name "*.cpp" \) \
-exec ggrep -qF LARGE_INTEGER {} \; \
-exec gsed -i '1s/^/#include <stdint.h>\n/' {} \;

1
我假设你xargs不支持-0--null不选择。如果是这样,请使用以下构造:

寻找 。 -type f -exec grep -lFZSOME_STRING{} + | xargs -0 gsed -s -i '命令'

即在你的情况下:

gfind /tmp/ -type f \( -name "*.h" -o -name "*.cpp" \) \
-exec ggrep -lFZ LARGE_INTEGER {} + | \
xargs -0 gsed -s -i '1s/^/#include <stdint.h>\n/'

它应该比第一个更有效率。
此外,两者都适用于所有类型的文件名。请注意,我使用的是grep-F固定字符串),因为它速度更快,因此如果您打算使用正则表达式,请将其删除。

答案2

只需通过管道将输出传递gfindxargs

gfind /tmp/ -type f \( -name "*.h" -o -name "*.cpp" \) -exec ggrep -l "LARGE_INTEGER" {} + | xargs sed -i '1s/^/#include <stdint.h>\n/'

请注意,我已从 中删除了该-P选项ggrep,因为您匹配的是固定字符串。

然而,这个解决方案不能很好地处理包含换行符的文件名;更安全的方法是强制gfind输出以 NULL 结尾的文件名并在循环中循环输出while

#!/bin/bash

gfind /tmp/ -type f \( -name "*.h" -o -name "*.cpp" \) -print0 | while read -d '' -r filepath; do
    [ "$(ggrep -l "LARGE_INTEGER" "$filepath")" ] && sed -i '1s/^/#include <stdint.h>\n/' "$filepath"
done

如果你喜欢单行本:

gfind /tmp/ -type f \( -name "*.h" -o -name "*.cpp" \) -print0 | while read -d '' -r filepath; do [ "$(ggrep -l "LARGE_INTEGER" "$filepath")" ] && sed -i '1s/^/#include <stdint.h>\n/' "$filepath"; done

相关内容