Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Recursive copy to relative destination paths

Tags:

bash

shell

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
like image 995
atxdba Avatar asked Apr 30 '12 22:04

atxdba


People also ask

Does chdir work with relative path?

Description: The chdir() function changes the current working directory to path, which can be relative to the current working directory or an absolute path name.

How do I copy a full path in Linux?

In order to copy a directory on Linux, you have to execute the “cp” command with the “-R” option for recursive and specify the source and destination directories to be copied.

How do I create a relative path to a file?

Relative pathRelative paths make use of two special symbols, a dot (.) and a double-dot (..), which translate into the current directory and the parent directory. Double dots are used for moving up in the hierarchy. A single dot represents the current directory itself.

What is an example of a relative path?

A relative path needs to be combined with another path in order to access a file. For example, joe/foo is a relative path.


2 Answers

Actually it also works with cp, what you want is the --parents flag.

cp --parents `find /path/src  \( -name "*.jpg" -o -name "*.gif" \)` /path/target

In theory -P is synonyms with --parents, but that never worked for me.

like image 106
rioki Avatar answered Sep 21 '22 17:09

rioki


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
like image 29
Paul R Avatar answered Sep 24 '22 17:09

Paul R