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 understand that the -exec can take a + option to mimic the behaviour of xargs. Is there any situation where you'd prefer one form over the other?

I personally tend to prefer the first form, if only to avoid using a pipe. I figure surely the developers of find must've done the appropriate optimizations. Am I correct?

share|improve this question

3 Answers 3

up vote 8 down vote accepted

You might want to chain calls to find (once, when you learned, that it is possible, which might be today). This is of course only possible as long as you stay in find. Once you pipe to xargs, it's out of scope.

Small example, two files a.lst and b.lst:

cat a.lst
fuddel.sh
fiddel.sh

cat b.lst
fuddel.sh

No trick here - simply the fact that both contain "fuddel" but only one contains "fiddel".

Assume we didn't knew that. We search a file which matches 2 conditions:

find -exec grep -q fuddel {} ";" -exec grep -q fiddel {} ";" -ls
192097    4 -rw-r--r--   1 stefan   stefan         20 Jun 27 17:05 ./a.lst

Well -maybe you know the syntax for grep or another program to pass both strings as condition, but that's not the point. Every program which can return true or false, given a file as argument, can be used here - grep was just a popular example.

And note, you may follow find -exec with other find commands, like -ls or -delete or something similar. Note, that delete not only does rm (removes files), but rmdir (removes directories) too.

Such a chain is read as a AND combination of commands, as long as not otherwise specified (namely with an -or switch (and parens (which need masking))).

So you aren't leaving the find chain, which is a handy thing. I don't see any advantage in using -xargs, since you have to be careful in passing the files, which is something find doesn't need to do - it automatically handles passing each file as a single argument for you.

If you believe you need some masking for finds {} braces, feel free to visit my question which asks for evidence. My assertion is: You don't.

share|improve this answer
    
This post has opened my eyes to a new way of using find. Thanks a lot! –  rahmu Feb 7 '13 at 1:49

Safely piping file names to xargs requires that your find supports the -print0 option and your xargs has the corresponding option to read it (--null or -0). Otherwise, filenames with unprintable characters or backslashes or quotes or whitespace in the name may cause unexpected behavior. On the other hand, find -exec {} + is in the POSIX find spec, so it is portable, and it is about as safe as find -print0 | xargs -0, and definitely safer than find | xargs. I'd recommend never doing find | xargs without -print0.

share|improve this answer
4  
A notable exception to the portability of find … -exec … {} + is OpenBSD, which only acquired this feature with version 5.1 released in 2012. All BSDs have had -print0 for several years, even OpenBSD (though it resisted that feature for a while too). Solaris, on the other hand, sticks to POSIX features, so you get -exec + and no -print0. –  Gilles Jun 27 '12 at 23:07

If you use the -exec ... ; form (remembering to escape the semicolon), you're running the command once per filename. If you use -print0 | xargs -0, you run multiple commands per filename. You should definitely use the -exec + form, which puts multiple files in a single command line and is much faster where appropriate.

A big plus of using xargs is the abilit to run multiple commands in parallel using xargs -P. On multi-core systems, that can provide huge time savings.

share|improve this answer
5  
You meant -P instead of -p. Keep in mind xargs -P is not in the POSIX standard, whereas find -exec {} + is, which is important if you are going for portability. –  jw013 Jun 27 '12 at 12:54
    
@Alexios You don't have to escape the plus sign, because it does not have a special meaning for the shell: find /tmp/ -exec ls "{}" + works just fine. –  daniel kullmann Jun 27 '12 at 13:48
1  
Corrent, of course. I've been escaping everything after the -exec for so long (I'm a masochist, I don't even use quotes to escape {}, I always type \{\}; don't ask), everything looks like it must be escaped now. –  Alexios Jun 27 '12 at 14:17
1  
@Alexios: If you find an example (except from being a masochist) where the masking of the braces is useful, please provide it as an answer to my question here - afaik this hint is outdated and only a relict in the manpage. I've never seen an example where find /tmp/ -exec ls {} + wouldn't work. –  user unknown Jun 27 '12 at 15:00
    
For me, this is muscle memory formed in the days of SunOS 4. Since I've been doing it for years, I completely failed to notice when bash started accepting the braces verbatim. I'm pretty sure at least one of the old shells I've used threw hissy fits if the braces weren't escaped. –  Alexios Jun 27 '12 at 15:05

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.