bash 如何在避免“太多论点”的同时进行 grep
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16086834/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I grep while avoiding 'Too many arguments'
提问by Justin S
I was trying to clean out some spam email and ran into an issue. The amount of files in queue, were so large that my usual command was unable to process. It would give me an error about too many arguments.
我试图清除一些垃圾邮件,但遇到了问题。队列中的文件数量太大,以至于我通常的命令无法处理。它会给我一个关于太多参数的错误。
I usually do this
我通常这样做
grep -i [email protected] 1US* | awk -F: '{print }' | xargs rm
1US* can be anything between 1US[a-zA-Z]. The only thing I could make work was running this horrible contraption. Its one file, with 1USa, 1USA, 1USb etc, through the entire alphabet. I know their has to be a way to run this more efficiently.
1US* 可以是 1US[a-zA-Z] 之间的任何值。我唯一能做的就是运行这个可怕的装置。它的一个文件,包含 1USa、1USA、1USb 等,贯穿整个字母表。我知道他们必须是一种更有效地运行它的方法。
grep -s $SPAMMER /var/mailcleaner/spool/exim_stage1/input/1USa* | awk -F: '{print }' | xargs rm
grep -s $SPAMMER /var/mailcleaner/spool/exim_stage1/input/1USA* | awk -F: '{print }' | xargs rm
采纳答案by Guido
Run several instances of grep. Instead of
运行多个 grep 实例。代替
grep -i [email protected] 1US* | awk '{...}' | xargs rm
do
做
(for i in 1US*; do grep -li user@domain "$i"; done) | xargs rm
Note the -l flag, since we only want the file name of the match. This will both speed up grep (terminate on first match) and makes your awk script unrequired. This could be improved by checking the return status of grep and calling rm, not using xargs (xargs is very fragile, IMO). I'll give you the better version if you ask.
注意 -l 标志,因为我们只想要匹配的文件名。这将加速 grep(在第一场比赛时终止)并使您的 awk 脚本不再需要。这可以通过检查 grep 的返回状态并调用 rm 来改进,而不是使用 xargs(xargs 非常脆弱,IMO)。如果你问,我会给你更好的版本。
Hope it helps.
希望能帮助到你。
回答by hek2mgl
you can use findto find all files which name's starting with the pattern '1US'. Then you can pipe the output to xargs which will take care, that the argument list will not growing to much and handle the grep call. Note that I've used a nullbyte to separate filenames for xargs. This avoids problems with problematicfile names. ;)
您可以find用来查找名称以模式“1US”开头的所有文件。然后,您可以将输出通过管道传输到 xargs,这将确保参数列表不会增长太多并处理 grep 调用。请注意,我使用空字节来分隔 xargs 的文件名。这避免了有问题的文件名的问题。;)
find -maxdepth 1 -name '1US*' -printf '%f# List the files that match
find /path/to/input/ -type f -exec grep -qiF [email protected] \{\} \; -print
# Once you're sure you've got it right
find /path/to/input/ -type f -exec grep -qiF [email protected] \{\} \; -delete
' | xargs -0 grep -u user@domain | awk ...
回答by MattH
The -execargument to findis useful here, I've used this myself in similar situations.
的-exec参数在find这里很有用,我自己在类似的情况下使用过这个。
E.g.
例如
ls 1US* | xargs grep -i [email protected] | awk -F: '{print }' | xargs rm
回答by Ziffusion
Using xargs is more efficient than using "find ... -exec grep" because you have less process creations etc.
使用 xargs 比使用“find ... -exec grep”更有效,因为你创建的进程更少等等。
One way to go about this would be:
解决这个问题的一种方法是:
find . -iname "1US*" -exec rm {} \;
But easier would be:
但更容易的是:
find . -name '1US*' | \
while read x; do grep -iq user@domain "$x" && rm "$x"; done
回答by Symaxion
Use findand a loop instead of xargs.
使用find和循环而不是xargs.
This uses pipes and loops instead of arguments (both for grepand rm) and prevents issues related with limits on arguments.
这使用管道和循环而不是参数(forgrep和rm)并防止与参数限制相关的问题。

