Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I grep while avoiding 'Too many arguments' [duplicate]

Tags:

linux

grep

bash

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 $1}' | 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.

grep -s $SPAMMER /var/mailcleaner/spool/exim_stage1/input/1USa* | awk -F: '{print $1}' | xargs rm
grep -s $SPAMMER /var/mailcleaner/spool/exim_stage1/input/1USA* | awk -F: '{print $1}' | xargs rm
like image 709
Justin S Avatar asked Apr 18 '13 15:04

Justin S


3 Answers

Run several instances of grep. Instead of

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.

Hope it helps.

like image 174
Guido Avatar answered Sep 23 '22 01:09

Guido


you can use find to 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 problematic file names. ;)

find -maxdepth 1 -name '1US*' -printf '%f\0' | xargs -0 grep -u user@domain | awk ...
like image 41
hek2mgl Avatar answered Sep 23 '22 01:09

hek2mgl


The -exec argument to find is useful here, I've used this myself in similar situations.

E.g.

# 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
like image 32
MattH Avatar answered Sep 22 '22 01:09

MattH