收到消息“-bash:/ usr / bin / grep:参数列表太长”

时间:2016-10-25 17:55:41

标签: bash grep

我试图通过grep命令计算子字符串的出现次数:

fatal error: folderB/fileB1.h: No such file or directory

文件数量接近20,000。我收到的消息是:

grep -il "touch screen" * | wc -l

这是否意味着文件太多了?什么是补救措施?我正在使用OS X.

2 个答案:

答案 0 :(得分:2)

从技术上讲,文件太多,但所有名称的总长度太大。当启动一个新进程时,你以一个字符串数组的形式将它的参数传递给它,操作系统对该数组允许的大小设置了硬性限制。

一个简单但效率低下的解决方案是不使用*扩展为grep的参数列表,而是在shell 内置中使用它命令:

for f in *; do
  grep 'touch screen' "$f"
done

这里,shell不会尝试将*扩展到的每个字符串传递到单个数组中,而是一次只使用一个元素。这需要对grep进行大量调用,因此更好的解决方案是使用一种工具,可以将路径名称扩展的结果批量化为较小的,可管理的集合。

find . -exec grep 'touch screen' {} +

此处,find会在每次调用时将尽可能多的文件传递给grep,重复此过程,直到所有文件都调用grep为止。

之前的两种技术都有效,因为grep在数论理论意义上是乘法。那是,     { grep '...' f; grep '...' g; }grep '...' f g生成相同的输出。如果您不能将命令拆分为较小子集上的多个调用,唯一的解决方案是希望命令可以从文件(命名文件或标准输入)读取参数。

答案 1 :(得分:1)

由于您尝试grep目录的所有文件,我建议您使用grep -R递归模式:

grep -ilR "touch screen" . | wc -l

应该等同于你的

grep -il "touch screen" * | wc -l

如果你的目录包含子目录,那么这两个命令会有所不同(但是你的当前grep命令会出错)。

另一种选择是在循环中对每个文件调用grep,然后wc -l循环的输出:

for file in *; do
    grep -il "touch screen" $file
done | wc -l

我对xargs发表了评论,将命令的输出作为另一个命令的参数传递确实很棒:

ls . | xargs -L 20 grep "touch screen" | wc -l

此处它将传递给grep的参数数量限制为20,并根据需要多次调用grep

但是,我不认为它可以用于*的扩展,而是需要像我展示的那样处理ls的输出。解析ls的输出很容易出错,因此我不推荐它。