11

I was getting ready to post this as a question, but after fiddling around with it a little longer, I found the solution. So I thought I would go ahead and post it here in case it helps someone else.

I had trouble with find -exec cmd +. I got the error:

$ find ./ -name "*JIM*" -exec cp {} $TARGET_DIR +
find: missing argument to `-exec'

It worked if I used

$ find ./ -name "*JIM*" -exec cp {} $TARGET_DIR \;

But I did't want to use that because it forks a new process for every file found.

And it worked if I used

$ find ./ -name "*JIM*" -exec ls {} +

It lists all of the files that I want to copy. But -exec cp {} $TARGET_DIR + didn't work.

The solution I found is:

$ find ./ -name "*JIM*" -exec cp --target-directory=$TARGET_DIR {} +

Where --target-directory= could also be replaced with -t

Hope this helps.

Rusty Lemur
  • 1,697
  • 1
  • 21
  • 54
  • 3
    It would be interesting if someone could explain *why* the first one fails. It's not entirely clear, but the man page seems to imply you can't have any further arguments between {} and +. – chepner Aug 21 '12 at 18:18
  • 2
    I'm curious to know why this post was closed as "off topic." From the scope defined by the community, it seems that this would fall under "software tools commonly used by programmers" category, and it includes the code that fixed a specific problem I had. If anyone who closed it could comment, I'd appreciate it. Thanks! – Rusty Lemur Aug 28 '13 at 14:57
  • Admittedly, it's a vague specification, but I've always interpreted "software tools commonly used by programmers" to mean compilers, linkers, debuggers, source-code control, etc., not general utilities. – chepner Aug 28 '13 at 15:50
  • I think it would be great if the question was moved to Super User. I find it very useful. – pabouk - Ukraine stay strong Oct 12 '13 at 23:49
  • See also: [*find -exec: add arguments between {} and +*](https://unix.stackexchange.com/q/615661/15654). – gerrit Oct 21 '20 at 12:17
  • Voted to "reopen" as it's part of bash/shell programming – Déjà vu Feb 18 '22 at 05:06
  • @chepner I was also wondering why the syntax has not been improved ; *find* is a beloved and powerful command, like eg *rsync*, but its syntax is prehistoric. – Déjà vu Feb 18 '22 at 05:13

1 Answers1

12

As mentioned in the opening post, the solution I found is:

$ find ./ -name "*JIM*" -exec cp --target-directory=$TARGET_DIR {} +

Where --target-directory= could also be replaced with -t

jli
  • 6,523
  • 2
  • 29
  • 37
Rusty Lemur
  • 1,697
  • 1
  • 21
  • 54
  • Great answer! Most important lesson is, exec takes only one `{}` and cmake must take `{} +` as last arg to pass terminate to exec. Hence in general, command ran by exec must be modified to take input from find as the last argument. – lashgar May 26 '20 at 15:15