Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I'm trying to run the following command:

find a/folder b/folder -name *.c -o -name *.h -exec grep -I foobar '{}' +

This is returning an error:

find: missing argument to -exec

I can't see what's wrong with this command, as it seems to match the man page:

-exec command {} +

This variant of the -exec option runs the specified command on the selected files, but the command line is built by appending each selected file name at the end; the total number of invoca- tions of the command will be much less than the number of matched files. The command line is built in much the same way that xargs builds its command lines. Only one instance of '{}' is allowed within the command. The command is executed in the starting directory.

I also tried:

find a/folder b/folder -name *.c -o -name *.h -exec grep -I foobar {} +
find a/folder b/folder -name *.c -o -name *.h -exec 'grep -I foobar' {} +
find a/folder b/folder -name *.c -o -name *.h -exec 'grep -I foobar' '{}' +
find a/folder b/folder -name "*.c" -o -name "*.h" -exec grep -I foobar '{}' +
find a/folder b/folder \( -name *.c -o -name *.h \) -exec grep -I foobar '{}' +
find a/folder b/folder -name *.c -o -name *.h -exec grep -I foobar '{}' \+
share|improve this question
    
Have you tried escaping the + at the end? find a/folder b/folder -name *.c -o -name *.h -exec grep -I foobar '{}' \+ –  jayhendren May 7 at 21:37
    
Yes, no dice there either. –  Koveras May 7 at 21:39
1  
You may be using an old version of GNU find. Though the -exec cmd {} + variant is POSIX and has been available since the 80s, GNU find only added it (relatively) recently (2005). What does find --version tell you? –  Stéphane Chazelas May 7 at 21:43
    
GNU find version 4.1 - it's the one that ships with git for Windows. –  Koveras May 7 at 21:44
2  
@Koveras, that would be it then. -exec {} + was added in 4.2.12 in 2005. In older GNU finds, you can use the (non-POSIX) -print0 | xargs -r0 to get something similar. 4.1 is from 1994. –  Stéphane Chazelas May 7 at 21:47

3 Answers 3

up vote 5 down vote accepted

You need to remove the backticks you use around {}. The -o requires a braces but can be simplified like this:

find a/folder b/folder -name "*.[ch]" -exec grep -I foobar {} +

Should you use an archaic GNU find version, this should work:

find a/folder b/folder -name "*.[ch]" -exec grep -I foobar {} \;
share|improve this answer
    
Oops, they were meant to be quotes not backticks. –  Koveras May 7 at 21:21
    
Quotes would be useless as {} has no specific meaning to the shell. –  jlliagre May 7 at 21:26
    
From find man pages: "The string '{}' is replaced by the current file name being processed everywhere it occurs in the arguments to the command, not just in arguments where it is alone, as in some versions of find. Both of these constructions might need to be escaped (with a '\') or quoted to protect them from expansion by the shell." –  Koveras May 7 at 21:29
    
I indeed read that in the manual page but the fact is there is no shell I'm aware of that requires quoting the curly braces. What shell are you using ? –  jlliagre May 7 at 21:37
    
bash. With or without the quotes I get the error anyways. –  Koveras May 7 at 21:38

“missing argument to -exec” usually means that the argument to -exec is missing its terminator. The terminator must either be an argument containing just the character ; (which needs to be quoted in a shell command, so it's typically written \; or ';'), or two successive arguments containing {} and +.

Stephane Chazelas has identified that you're using an older version of GNU find which doesn't support -exec … {} +, only -exec {} \;. Although GNU was a late adopter of -exec … {} +, I do recommend that you get a less antique tool suite (such as Cygwin, which includes git and a whole lot more, or GNUwin32, which lacks git but doesn't have the bad-employee-trying-to-use-linux-but-we-impose-windows vibe that Cygwin gives). This feature was added in version 4.2.12, over 9 years ago (it was the last identified feature to make GNU find POSIX-compliant).

If you want to stick to an older GNU find, you can use -print0 with xargs -0 to get a similar functionality: grouped command execution, supporting arbitrary file names.

find a/folder b/folder -name '*.c' -o -name '*.h' -print0 | xargs -0 grep -I foobar /dev/null

Always quote the wildcards on the find command line. Otherwise, if you happen to run this command from a directory containing .c files, the unquoted *.c would be expanded to the list of .c files in the current directory.

Adding /dev/null to the grep command line is a trick to ensure that grep will always print the file name, even if find happens to find a single match. With GNU find, another method is to pass the option -H.

share|improve this answer
    
What do you mean by bad-employee-trying-to-use-linux-but-we-impose-windows vibe that cygwin gives? –  Koveras May 16 at 20:36
    
GNUwin32 doesn't have expect :( –  Koveras May 17 at 16:18

I had my share of headaches with the exec syntax in the past. most days now I prefer the nicer bash syntax:

for f in `find a/folder b/folder -name "*.[ch]"`; do grep -I foobar $f; done

It has some limitations when you want to treat the files as a group, as each is evaluated serially, but you can pipe the output elsewhere just fine

share|improve this answer
1  
While this tends to work it is significantly less useful than the pure-find version because it cannot handle files with whitespace in the name correctly. –  Etan Reisner May 8 at 3:35
1  
No, don't do this. This breaks as soon as the files contain spaces and other “weird” characters. This is also more complex and slower than find … -exec … \;, so there's no reason to use this even if you know that your file names are tame. –  Gilles May 8 at 3:44

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.