Reputation: 5417
This problem has been discussed extensively but I couldn't find a solution that would help me.
I'm trying to selectively copy files from a directory tree into a specific folder. After reading some Q&A, here's what I tried:
cp `find . -name "*.pdf" -type f` ../collect/
I am in the right parent directory and there indeed is a collect
directory a level above. Now I'm getting the error: cp: invalid option -- 'o'
What is going wrong?
Upvotes: 2
Views: 2041
Reputation: 113994
To handle difficult file names:
find . -name "*.pdf" -type f -exec cp {} ../collect/ \;
By default, find
will print the file names that it finds. If one uses the -exec
option, it will instead pass the file names on to a command of your choosing, in this case a cp
command which is written as:
cp {} ../collect/ \;
The {}
tells find
where to insert the file name. The end of the command given to -exec
is marked by a semicolon. Normally, the shell would eat the semicolon. So, we escape the semicolon with a backslash so that it is passed as an argument to the find
command.
Because find
gives the file name to cp
directly without interference from the shell, this approach works for even the most difficult file names.
The above runs cp
on every file found. If there are many files, that would be a lot of processes started. If one has GNU tools, that can be avoided as follows:
find . -name '*.pdf' -type f -exec cp -t ../collect {} +
In this variant of the command, find
will supply many file names for each single invocation of cp
, potentially greatly reducing the number of processes that need to be started.
Upvotes: 3