逻辑运算符可以与find和xargs一起使用吗?

时间:2017-01-16 18:51:54

标签: bash loops find xargs

我有一个大约5000个文件的目录,其中一些错误地写入了语法错误。我使用以下代码来识别哪些文件有错误:

ls -1 | while read a; do grep -q '^- ' $a || echo $a; done

我最初尝试使用findxargs的组合,但我无法弄清楚如何添加我需要的布尔逻辑。

我的用例不是I / O绑定并且足够快地完成。但我很好奇,看看是否可以在不依赖bash循环的情况下完成相同的操作。虽然对Bash感到满意,但我倾向于严重依赖管道进入循环,这通常导致mind numbingly slow performance

3 个答案:

答案 0 :(得分:3)

您可以将布尔逻辑与find

一起使用
find -maxdepth 1 -type f \( -exec grep -q '^- ' {} \; -o -print \)

-o选项是逻辑OR。如果-exec执行的命令将返回非零返回值-print将打印文件名。

答案 1 :(得分:2)

以下是使用grep -L

执行此操作的另一种方法
find -maxdepth 1 -type f -exec grep -L '^- ' {} \;

上面的代码会列出目录中所有文件,这些文件的内容中不包含以dash + space -开头的行。

要使上面的代码递归(即,将搜索扩展到所有子目录),只需删除-maxdepth 1部分。

man grep关于选项-L

  

-L, - files-without-match抑制正常输出;而是打印每个输入文件的名称,通常没有输出   打印。扫描将在第一场比赛中停止。

答案 2 :(得分:2)

单独使用grep就足够了:

grep -d skip -L '^- ' *

注意:与find不同,这不会自动包含隐藏文件。
要以递归方式搜索,请改用grep -L '^- ' -R .(尽管-R不符合POSIX标准,但它适用于GNU和BSD / macOS grep)。

-L,如Jamil Said's helpful answer中所述,打印包含搜索词的每个输入文件的路径(如指定的那样) 。

-d skip跳过目录(而选项-d不符合POSIX标准,GNU和BSD / macOS grep都支持它。

警告:正如hek2mgl在评论中指出的那样,* 的文件名扩展之后产生的命令行可能太长,导致/usr/bin/grep: Argument list too long等错误 (相反,如果您使用grep递归搜索-R .,则您不会遇到此问题。)

最大。长度是特定于平台的,可以使用 getconf ARG_MAX 查询,但请注意实际限制低于 ,具体取决于关于环境的大小 - 请参阅this article

实际上,5000个文件可能不会出现问题,即使在最大值相对较低的平台上也是如此。长度,例如macOS - 除非你有特别长的文件名和/或你的globbing模式有一个冗长的路径组件 [1]
最近的Linux版本有更高的限制。

如果达到了限制并且必须解决此问题,使用xargs ,如下所示:

printf '%s\0' * | xargs -0 grep -d skip -L '^- '

请注意,虽然读取NUL终止输入的-0不符合POSIX标准,但GNU和BSD / macOS xargs都支持它。

如果输入文件名确实不适合单个命令行,xargs将以导致最少grep次调用的方式对输入进行分区必须处理所有这些。

[1] macOS 10.12的限制为262,144字节(256 KB);如果我们保守地假设,在扣除环境的大小和命令行的固定部分之后,我们的文件名列表得到250,000字节,这给了我们每个文件名250000 / 5000 == 50个字节+空格(列表分隔符),以便允许每个文件名长达49个字节 相比之下,Ubuntu 16.04的限制高出8倍:2,097,152字节(2 MB)。