Recursive copy to relative destination paths

bash, shell

Solution

You can use rsync for this, e.g.

$ rsync -avm /path/src/ /path/dest/ --include \*/ --include \*.jpg --include \*.gif --exclude \*

Just to clarify the above:

-avm             # recursive, copy attributes etc, verbose, skip empty directories
/path/src/       # source
/path/dest/      # destination (NB: trailing / is important)
--include \*/    # include all directories
--include \*.jpg # include files ending .jpg
--include \*.gif # include files ending .gif
--exclude \*     # exclude all other files

Problem

I was thinking something like what I'm trying to accomplish could be done with built in shell tools w/o the need for a more complicated script. I'd like to find all the files in a path and copy them to a destination basepath retaining the relative paths they were found in. Example: Say I ran: ``` [~:] find /path/src \( -name "*.jpg" -o -name "*.gif" \) ``` and that returned: ``` /path/src/a.jpg /path/src/dir1/b.jpg /path/src/dir2/dir3/c.gif ``` I'd like them to all end up in: ``` /path/dest/a.jpg /path/dest/dir1/b.jpg /path/dest/dir2/dir3/c.gif ``` I tried an `-exec cp {} /path/dest \;` flag to `find` but that just dumped everything in /path/dest. E.g: ``` /path/dest/a.jpg /path/dest/b.jpg /path/dest/c.gif ```

Original source