0

I tried to find files and move them to another folder

$ find ~ -iregex ".*cheat.*\.pdf" -exec mv "{}" cheatSheet +
find: missing argument to `-exec'

However, the test works

find ~ -iregex ".*cheat.*\.pdf" -exec echo {} +

What's the problem with my usage?

Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255
Wizard
  • 2,503

2 Answers2

1

The {} needs to be a the end of the -exec command. The mv command supports this with the -t option:

mv [OPTION]... -t DIRECTORY SOURCE...

So your command would be:

find ~ -iregex ".*cheat.*\.pdf" -exec mv -t cheatSheet "{}" +
1

When using -exec ... {} +, the {} must be at the end, just before the +.

This means that you would have to use

-exec mv -t cheatSheet {} +

which would require access to GNU mv. Without GNU mv, you would use

-exec mv {} cheatSheat \;

to move one file at a time, or

-exec sh -c 'mv "$@" cheatSheet' sh {} +

to call an in-line script that moves all files in one go.

You additionally don't need -iregex. The following will be easier to read and understand:

find "$HOME" -ipath '*cheat*.pdf' \
    -exec sh -c 'mv "$@" cheatSheet' sh {} +

or, for clarity, either one of the following which does what you actually mean (it depends on whether you want cheat to be part of the filename at the end of the path (the first alternative), or one of the directory names in the path (the second alternative)):

find "$HOME" -iname '*cheat*.pdf' \
    -exec sh -c 'mv "$@" cheatSheet' sh {} +

find "$HOME" -ipath 'cheat/' -iname '.pdf'
-exec sh -c 'mv "$@" cheatSheet' sh {} +

Note that -ipath is a GNU find extension, but that -iname, though non-standard, is more commonly implemented.

Also worth noting is that if you have name collisions, i.e. files with exactly the same name, you will overwrite some already moved files in the process of moving other files. With GNU mv, you may avoid this by using either the -n option (will not clobber existing files) or the -b option (rename/backup existing files).

Related:

Kusalananda
  • 333,661