Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

osx find exec rm find: exec: unknown primary or operator

Tags:

find

bash

unix

rm

I've got a bunch of files that end in "-e" that I want to remove.

$ find . -name "*-e" exec rm {} \;
find: exec: unknown primary or operator

Is the regex expanding in some way that messes everything up?

like image 795
freedrull Avatar asked Jan 13 '15 05:01

freedrull


3 Answers

It should be:

find . -name "*-e" -exec rm '{}' \;

Or better:

find . -name "*-e" -exec rm '{}' +

As per man find:

-exec utility [argument ...] {} +
   Same as -exec, except that ``{}'' is replaced with as many pathnames as possible for 
   each invocation of utility. This behaviour is similar to that of xargs(1).
like image 69
anubhava Avatar answered Oct 22 '22 22:10

anubhava


+1 to @anubhava's answer. However, I did have to be very careful before it worked:

TLDR: the format is -exec <your-command> {} \;

Hint: use something harmless, like echo to get it working first.

find . -name "*.sh" -exec echo {} \;

./081.documentation/000.sticky.list_url_info_markdown/worklocal.sh
./081.documentation/001.fixed.p2.collab_diagrams/common.sh
./081.documentation/001.fixed.p2.collab_diagrams/worklocal.sh

Once it works you can get all fancy with extra find options as in

find . -name "*.sh" -maxdepth 3 -exec echo {} \;

Be sure to use -exec, not --exec or exec

remember that find’s options all take 1 dash. -exec is no different.

find . -name "*.sh" --exec echo {} \;

find: --exec: unknown primary or operator

find . -name "*.sh" exec echo {} \;

find: exec: unknown primary or operator

Notice how what comes after find: reflects what you put in? Here find has no idea what’s going on so you get a generic I don't know message.

Once you are using -exec terminate with \; - that space is critical

find . -name "*.sh" -exec echo {}\;

find: -exec: no terminating ";" or "+"
.................👆 you want to see -exec in your error message. that part is good ✅ find knows what it is looking at so it has -exec related messages.

Finally, replace echo with your actual payload:

find . -name "*.sh" -exec reformat.py --myfancy-option-to-reformat {} \;

'{}' vs {} made no difference whatsoever.

It might, under some conditions, maybe if your paths have spaces in them so if you’re unsure put the quotes. But I couldn't trigger any errors even with spaces and with different commands (cat, ls) than echo.

find . -name "*.sh" -exec echo {} \;

./bar zoom.sh
./foo.sh
./worklocal.sh

find . -name "*.sh" -exec echo '{}' \;

./bar zoom.sh
./foo.sh
./worklocal.sh

I'm not saying the quotes are useless, I am saying they're not causing unknown primary or operator.

ending with + strips newlines between invocations:

Don't forget that space before the +.

find . -name "*.sh" -exec echo {} +

./bar zoom.sh ./foo.sh ./worklocal.sh

Yes, I dream of a more user-friendly find. But macos's Spotlight-related mdfind is, by light-years, even more unfriendly when it comes to options

like image 39
JL Peyret Avatar answered Oct 23 '22 00:10

JL Peyret


use find delete args:

find ./ -name "*-e" -delete
like image 3
JohnDHH Avatar answered Oct 23 '22 00:10

JohnDHH