Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

I have a folder 'foo' that contains a lot of sub folders, e.g.

foo
 |---20101
 |---20102
 |---20103
 |---20111
 |---20112
 |---20113

There are way more than this, but hopefully it explains the scenario. I now want to copy all folders from this folder that start '2011' into a sibling of 'foo' called 'bar'. However, 'bar' already contains some folders with the same name

bar
 |---20111
 |---20113
 |---20114

The contents of the source and destination folder should be merged. Notice that the script will also need to create a bar/20112 folder as that doesn't exist.

I'm new to Mac Terminal scripting and have successfully managed to grep the right folders

foo>ls | grep ^2011 

Which lists the right folders, but I've no idea how to pipe that over to an appropriate copy operation.

share|improve this question
add comment

1 Answer

up vote 4 down vote accepted

The copy command is cp. If you give it the -r (recursive) flag, it will do exactly what you want, it will copy files into existing folders and create new folders when the destination folder is missing.

However, you should never parse the output of ls, you should use find or, even simpler, bash globbing:

cp -rv foo/2011* bar/

If there are files as well as folders whose name begins with 2011, use find and its -exec option which will apply whatever command you give it to everything found by find (referred to as {}):

find foo/ -type d -name "2011*" -exec cp -rv '{}' bar/ \;

In this specific case there is no reason to save the output of a command and pass it to cp. This is sometimes necessary though so here's how its done. In general, the output of a command can be given as input to another command if placed inside inverted comas or $().

cp -rv `find foo/ -type d -name "2011*"` bar/

or

cp -rv $(find foo/ -type d -name "2011*") bar/

Alternatively, you can loop through the results:

for dir in $(find foo/ -type d -name "2011*"); do cp -rv "$dir" bar/; done

This gets more complicated if your file/folder names can contain special characters or new lines and the like, in that case you should do something like this:

find foo/ -type d -name "2011*" | while IFS= read -r dir; do 
       cp -rv "$dir" bar/; 
done
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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