ankush981
ankush981

Reputation: 5417

Copy specific files recursively

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

Answers (1)

John1024
John1024

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.

More efficiency

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

Related Questions