我想要在Maildir目录中跨越500个文件进行grep。我发布了命令
grep MyPattern *我收到了错误消息:
bash: /usr/bin/grep: Argument list too long因此,我将文件列表存储在一个文件MyFiles中,并发出以下命令
for i in $(`cat MyFiles`); do echo $i; done在做grep之前,我想做一个回音,就像检查一样。但是这给出了以下错误
bash: 1434361691.M617282P6399V0000000000000808I00000000000E16C1_23.ananda-linux,S=10055:2,S: command not found1434年..。问题是目录中的第一个文件。
回到原来的问题。如何在邮箱中跨越所有这些文件。我有更大的邮箱,里面有50000多封电子邮件。
发布于 2018-04-26 08:07:41
通过从当前目录递归,让grep自己构造文件列表:
grep -r MyPattern .这与*不太一样,因为它将在子目录中搜索,但是对于邮件目录,这通常是您想要的。
发布于 2018-04-26 09:14:38
当shell执行外部命令时,在展开任何文件名全局模式(如* )后,命令行的长度不得超过特定长度。
在您的示例中,grep 'PATTERN' *扩展为一个过长的命令,使得shell无法执行。
在第二个例子中:
for i in $(`cat MyFiles`); do echo $i; done您试图迭代存储在MyFiles中的文件名,但是语法非常错误。
$(`cat MyFiles`)是相同的
$( $(cat MyFiles) )这意味着MyFiles的内容将被解释为一个命令。这就是您获得command not found错误的原因。
有几种方法可以纠正这种情况,但是遍历文件的内容并不是一个很好的方法。
在他的回答中给出了一个很好的解决方案,另一个解决方案是,假设当前工作目录是Maildir文件夹,
find . -type f -exec grep 'PATTERN' {} +这将在尽可能大的批文件上执行几次grep。
这类似于
printf '%s\n' * | xargs grep 'PATTERN'但是find命令使用空格和嵌入的换行符来处理文件名。
这里的printf命令将每一行输出一个文件名。它没有遇到与grep 'PATTERN' *相同的问题,因为它很可能是内置命令,因此不必由shell作为外部命令执行。
您的循环解决方案也可以工作,但与其循环cat的输出,不如简单地执行以下操作
for name in *; do
grep 'PATTERN' "$name"
done这假定当前目录中只有常规文件。
若要确保只处理邮件消息,可以使用
for name in *,*; do
grep 'PATTERN' "$name" /dev/null
done这将迭代至少包含一个逗号的名称。我还添加了/dev/null,以强制grep输出与给定模式匹配的文件名。您可以删除/dev/null,如果-H支持grep,则可以将其与D22一起使用。
这样的循环很慢,因为我们对目录中的每个文件执行一次grep。
https://unix.stackexchange.com/questions/440148
复制相似问题