我正在尝试将标准 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退出代码 0
sosed
仅当文件包含时才会处理有问题的文件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
只需通过管道将输出传递gfind
到xargs
:
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