15

I use the following command to clear a directory, of files and directories over 30 days old, and move them to an archive directory which I can delete after a few weeks if nobody asks for their files back. The target directory has subdirectories by user name, so will the archive directory.

This is the command I use:

find /path/to/directory/username/ -mtime +30 -exec mv "{}" /path/to/archive/username/ \;

I suggested a modified version of this to answer a question on ask ubuntu, another user edited the code to change the end of line \; for + as it's faster(and more correct?). See here

However, using + in this way works if the -exec command is ls -lh but not in the actual command that I use. If I try it with + I get an error message:

find: missing argument to '-exec'

I don't understand why it's behaving this way, or what the correct command would be. Please don't just post a command correction, I'd like to understand rather than just follow a suggestion blindly.

  • Are you referring to this answer? Thismight explain why – Wilf Jul 8 '15 at 13:49
  • Thanks @Wilf I've updated to show which answer the edit happened on. The link you provided, has a further link which explains it in a manner that my brain can cope with. – Arronical Jul 8 '15 at 13:54
  • Thanks @souravc in a brilliantly cyclic manner that question is by the user that edited my command! Finally I get it + supplies multiple arguments to the same command, but mv can't cope with that! – Arronical Jul 8 '15 at 14:01
  • @Arronical mv can, see my answer^^ – chaos Jul 8 '15 at 14:01
19

The user in that post may said that the + sign at the end of a -exec command is faster, but not why.

Lets assume the find command return the following files:

/path/to/file1
/path/to/file2
/path/to/file3

The normal -exec command (-exec command {} \;) runs once for each matching file. For example:

find ... -exec mv {} /target/ \;

Executes:

mv /path/to/file1 /target/
mv /path/to/file2 /target/
mv /path/to/file3 /target/

If you use the + sign (-exec command {} +) the command is build by adding multiple matched files at the end of the command. For example:

find ... -exec mv -t /target/ {} +

Executes:

mv -t /target/ /path/to/file1 /path/to/file2 /path/to/file3

To use the + flag correctly the argument to process must be at the end of the command, not in the middle. That's why find trows missing argument to '-exec' in your example; it misses the closing {}.

  • I've always wondered why find -exec requires the {} to be the last arg, when used with +. Anyone know why that design decision was made, instead of letting constructs like the OP's command line work? – Peter Cordes Jul 9 '15 at 3:05
11

The user explained their edit....

'+' exec's terminator is faster than '\;' see https://askubuntu.com/questions/558817/what-is-the-difference-between-using-and-in-exec-command; and creating a backup file from original file is good idea

...using this link. I think basically instead of using multiple commands, it sends all the filenames to one command instance, to speed things up. Here is a example from here:

Using -exec with a semicolon (find . -exec ls '{}' \;), will execute

ls file1
ls file2
ls file3

But if you use a plus sign instead (find . -exec ls '{}' \+), all filenames will be passed as arguments to a single command:

ls file1 file2 file3

There are other forms available using ; and + as well (from here:)

Therefore the following example syntax is allowed for find command:

find . -exec echo {} \;
find . -exec echo {} ';'
find . -exec echo {} ";"
find . -exec echo {} \+
find . -exec echo {} +

HOWEVER, I'm not sure this will work with the move command anyway, as it's syntax is mv [OPTION]... SOURCE DEST, unless the -t option or similar is used. However it should work with ls with no extra options etc as they can understand when multiple filenames are given. The + may also need to be escaped (i.e. \+)

  • Both great answers, but I've got to give it to chaos for being a tiny bit quicker, and explaining the mv -t, both +1s though! – Arronical Jul 8 '15 at 14:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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