我试图通过grep命令计算子字符串的出现次数:
fatal error: folderB/fileB1.h: No such file or directory
文件数量接近20,000。我收到的消息是:
grep -il "touch screen" * | wc -l
这是否意味着文件太多了?什么是补救措施?我正在使用OS X.
答案 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
的输出很容易出错,因此我不推荐它。