在 UNIX 中:文件夹中有.sas
扩展名为 (programs) 的文件和扩展名为.sas7bdat
(tables) 的文件。我需要查找包含文本“liasse”的程序(而不是表格)。我尝试启动以下命令:
grep -rli liasse *.sas ./
在结果中我可以看到一个表名。仅检索程序的命令应该是什么?
答案1
这是一个符合 POSIX 标准的命令,可以grep
同时启动多个文件:
find . -type f -name '*.sas' -exec grep -li liasse {} +
您的命令grep -rli liasse *.sas ./
没有按预期工作。让我们分析一下发生了什么:
*.sas
经历 shell 全局变换。- 如果当前目录中至少有一个对象匹配
*.sas
,则所有匹配的对象都会被放置在 之后liasse
。 - 如果不存在这样的对象,
grep
可能会获取文字*.sas
作为要检查的路径(这取决于;例如shopt -s nullglob
,shopt -s failglob
调查bash
)并抛出警告。 - 不管哪种方式,都会在搜索内部文件时递归
grep
获取并处理它。这将处理程序、表格等下的所有文件。./
liasse
./
这就是为什么您可以在结果中得到表名。
我的命令仅针对与模式匹配的文件find . -type f -name '*.sas' -exec grep -li liasse {} +
运行。重要事项:grep
*.sas
-type f
仅选择常规文件。这样我就可以防止目录名称匹配*.sas
(如果有的话)不会被传递给grep
(grep
没有的话-r
无论如何都应该拒绝它们,但这不太优雅)。- 引用该模式可防止 shell 进行通配符;
find
将文字*.sas
作为操作数的参数-name
;它知道如何解释这样的模式。 find … -exec … {} +
语法用多个对象代替{}
。与 相比,这样grep
可以创建更少的进程(可能只有一个)find … -exec … {} \;
。
答案2
您可以使用find
命令按名称递归查找所有文件,然后grep
对每个文件运行。最简单的解决方案是-exec
find 选项:
find . -name '*.sas' -exec grep -li liasse {} \;
或者,您可以结合find
使用xargs
:
find . -name '*.sas' -print0 | xargs -0 grep -li liasse
这具有稍微好一点的性能,因为它grep
针对一大批文件执行,而不是针对每个文件执行。
使用-P
选项xargs
,您甚至可以并行运行多个 grep 调用。
答案3
这可以通过以下方式实现
find . -type f -name "*.sas" -print0 | "xargs" -0 -e grep -liH -e liasse
如果你没有使用选项xargs
的实现-0
,即在find
和之间传达一组路径xargs
,你可以尝试
find . -type f -name "*.sas" -print | "xargs" -e grep -liH -e liasse