Wildcard not working in cp command when using exec

4

I want to copy all the files in all the directories to the parent directory, but I get the error

./img/* is not a directory

For example. Here is the command that I used. Is there a better way to do this?

find . -type d -regex './[a-z]*' -exec cp -v {}/* .. \;

m0meni

Posted 2015-02-19T02:56:39.390

Reputation: 155

Answers

4

Try:

find . -type d -regex './[a-z]*' -exec bash -c 'cp -v "$1"/* ..' Cp {} \;

Discussion

Consider:

find . -type d -regex './[a-z]*' -exec cp -v {}/* .. \;

When bash sees this line, it performs pathname expansion on {}/*. Since there (typically) is no directory named {}, the * is left as a literal *. This is not what you want. You need pathname expansion to occur after find has substituted in for {}. By putting the cp command in quotes and passing it as an argument to bash -c, we achieve that goal.

A sample form for bash -c looks like:

bash -c 'code...' a b c 

This tells bash to assign a to $0, b to $1, c to $2 and then execute code.... If an error occurs, the shell uses $0 as the name of the program being executed (in the error message). Above, we chose Cp as a descriptive name. Also, as above, {} is substituted for $1 and we use use $1 in the code.... When used this way, {} doesn't need to be quoted (but it doesn't hurt if you do); find handles any escaping that is needed. Inside code..., however, $1 should be in double-quotes to protect against word splitting and pathname expansion.

John1024

Posted 2015-02-19T02:56:39.390

Reputation: 13 893

Thank you very much! Could you explain why it works now? – m0meni – 2015-02-19T03:11:21.930

@AR7 I just updated the answer. Let me know if that helps. – John1024 – 2015-02-19T03:13:22.053

It helps very much. You've made my day. – m0meni – 2015-02-19T03:15:34.380

1

This might also work

cd your_directory
cp -rp * /absolut_path_to_parent_directory

ryder

Posted 2015-02-19T02:56:39.390

Reputation: 147