Why might -exec affect the output of find in Linux?

3

1

If I run this command...

sudo find /storage -name "*~" -or -name ".*~" -or -name "#.*#"
-or -name ".DS_Store" -or -name "Thumbs.db"

... it gives me a list of matching files, as expected. However, if I use this command...

sudo find /storage -name "*~" -or -name ".*~" -or -name "#.*#"
-or -name ".DS_Store" -or -name "Thumbs.db" -exec rm -v {} \;

... nothing is deleted. Similarly, with echo, nothing is printed...

sudo find /storage -name "*~" -or -name ".*~" -or -name "#.*#"
-or -name ".DS_Store" -or -name "Thumbs.db" -exec echo {} \;

How come?

Nick Bolton

Posted 2010-01-12T21:48:34.537

Reputation: 2 941

Answers

2

You've got to group your expression correctly - currently the -exec only applies to the last -or branch.

sudo find /storage \( -name "*~" -or -name ".*~" -or -name "#.*#" -or -name ".DS_Store" -or -name "Thumbs.db" \) -exec rm -v {} \;

Just remember that -exec is just an expression that returns true if the command returns zero, so running the command is just a side-effect.

Douglas Leeder

Posted 2010-01-12T21:48:34.537

Reputation: 1 375

@Douglas Leeder - Came across this example that helped me answer my own question at http://superuser.com/questions/474439/find-missing-argument-to-exec-when-executing-the-find-command-in-linux however I don't quite follow the statement so running the command is just a side-effect. What do you mean by that exactly?

– PeanutsMonkey – 2012-09-15T07:33:25.747

especially note the escaped parentheses \( and \) -- this prevents the shell from interpreting them; in this case you want find to handle them as part of the expression. this and other good examples on the find manpage: http://linux.about.com/od/commands/l/blcmdl1_find.htm

– quack quixote – 2010-01-12T22:16:31.737

Seems my workaround wasn't necessary, works like a charm, cheers. – Jeffrey Vandenborne – 2010-01-12T23:02:37.680

0

find Documents/ -iname '*.txt' -exec echo {} \;
 -or -iname '*.cpp' -exec echo {} \;

This however works. Hope this can help you further a little. If you use exec separately with all -or's the command will work.

I've found an alternative to your problem though.

for file in $(find Documents/ -iname '*.txt' 
-or -iname '*.cpp'| awk '{print $1}'); do rm $file; done

Jeffrey Vandenborne

Posted 2010-01-12T21:48:34.537

Reputation: 438