Tuesday, 25 June 2013

Copy files in a directory tree matching pattern(s) while preserving the relative path

Have you ever wanted to copy all files of a certain type from a large directory tree to an identical directory tree?

For example, one time I needed to copy all the .so files from /var/lib/gems to the vendor directory because for some reason, dependencies didn't. Copying all files didn't appeal to me, so I made this script.

Example (greyed out directory entries for easier viewing):
$ du -a /source/path
0    /source/path/something.else
0    /source/path/dir/another/directory/or/two/3.txt
4    /source/path/dir/another/directory/or/two
8    /source/path/dir/another/directory/or
12   /source/path/dir/another/directory
16   /source/path/dir/another

0    /source/path/dir/2.txt
20   /source/path/dir
0    /source/path/directory/containing/no/txt/files/not_a_txt_file
4    /source/path/directory/containing/no/txt/files
8    /source/path/directory/containing/no/txt
12   /source/path/directory/containing/no
16   /source/path/directory/containing
20   /source/path/directory

0    /source/path/1.txt
44   /source/path
$ copy-files-matching-pattern-preserving-path /source/path "*.txt" /destination/path Copying *.txt from /source/path to /destination/path...
/source/path/dir/another/directory/or/two/3.txt ==> /destination/path/dir/another/directory/or/two/3.txt
/source/path/dir/2.txt ==> /destination/path/dir/2.txt
/source/path/1.txt ==> /destination/path/1.txt
$ du -a /destination/path
0    /destination/path/dir/another/directory/or/two/3.txt
4    /destination/path/dir/another/directory/or/two
8    /destination/path/dir/another/directory/or
12   /destination/path/dir/another/directory
16   /destination/path/dir/another

0    /destination/path/dir/2.txt
20   /destination/path/dir
0    /destination/path/1.txt
24   /destination/path

It's basically a bash script for copying all files in a directory tree matching one or more specified patterns (such as *.txt) to another tree, creating any directories not already existing. It copies only the path below the source directory to the destination, and only creates directories with files matching the pattern.


  1. http://superuser.com/questions/299938/how-can-i-recursively-copy-files-by-file-extension-preserving-directory-structu

  2. short version:

    cd /top/level/to/copy
    find . -name '*.txt' | cpio -pdm /path/to/destdir

  3. Well, you can use Long Path Tool for such problems....