Using find with -exec gzip and grep

0

1

I have a bunch of zipped up log files and I want to search them all for a string. I tried this but it's not working:

find ./ -name "*.log.zip" -exec gzip -dc {} | grep ERROR \;

It's giving me:

find: incomplete statement
grep: can't open ;

What I want is, for each .log.zip file, unzip it and grep the output for "ERROR". Doing this on AIX, for what it's worth.

mluisbrown

Posted 2013-04-08T10:21:15.613

Reputation: 121

btw, I've managed to get the result I wanted by putting the -exec commands in a separate script and then using -exec script {} ; But I'd still like to know why the above doesn't work and if it's possible to do what I want without creating an intermediate script. – mluisbrown – 2013-04-08T10:45:28.207

Answers

0

There is an error in your syntax. Find is looking for \; or \+, but reads |. Grep is trying to open a file called ";". The difference between terminating -exec with a semicolon or a plus is running the command once for all files (+) and running the command once for every file (;).

Try this:

find ./ -name "*.log.zip" -exec zcat {} \+ | grep ERROR
# or
find ./ -name "*.log.zip" -exec sh -c 'zcat {} | grep ERROR' \;

Ярослав Рахматуллин

Posted 2013-04-08T10:21:15.613

Reputation: 9 076

The semicolon must be escaped with \ because it means something to the shell (end statement). The plus does not have to be escaped with bash. – Ярослав Рахматуллин – 2013-04-08T11:12:43.823

The first option works if I use gzip -dc but not with zcat, which gives a foo.log.zip.Z: No such file or directory error. The second option I'd already tried, and doesn't work as the {} substitution doesn't work. If I use gzip it gives a {}.gz: No such file or directory for each file. For zcat: {}.Z: No such file or directory. – mluisbrown – 2013-04-08T14:11:38.237

Then use the first version with gzip -dc. It's not entirely misguided to assume that most command line questions here are about GNU tools, specify the platform you are on and the version of the tools if that in not your case. – Ярослав Рахматуллин – 2013-04-08T14:51:42.537

I specified that I was running on AIX in the original post. However, the question of gzip or zcat is not that relevant. I'm more curious as to why in your 2nd solution the {} substitution does not happen, especially as the \+ find syntax cannot be applied to all such similar situations. – mluisbrown – 2013-04-08T15:02:33.067

Sorry for being inattentive, clearly I didn't recognize the OS tag. My guess is that the find on AIX reads the option to the -c argument of sh as a literal string and does no substitution. You could try something like -exec sh -c 'zcat '{}'| grep ERROR', but it's probably more effective to read the notes about -exec option in the manual than trying to "fool" the command. You could also use xargs, which has the -I flag (GNU find, but maybe AIX too) that specifies what {} should be. Such as: find /dir | xargs -I% gzip -dc % | grep ERROR. – Ярослав Рахматуллин – 2013-04-08T16:20:13.670