Search code examples
bashunixcp

Copy all files with a certain extension from all subdirectories and preserving structure of subdirectories


How can I copy specific files from all directories and subdirectories to a new directory while preserving the original subdirectorie structure?

This answer:

find . -name \*.xls -exec cp {} newDir \;

solves to copy all xls files from all subdirectories in the same directory newDir. That is not what I want.

If an xls file is in: /s1/s2/ then it sould be copied to newDir/s1/s2.

copies all files from all folders and subfolders to a new folder, but the original file structure is lost. Everything is copied to a same new folder on top of each other.


Solution

  • You can try:

    find . -type f -name '*.xls' -exec sh -c \
    'd="newDir/${1%/*}"; mkdir -p "$d" && cp "$1" "$d"' sh {} \;
    

    This applies the d="newDir/${1%/*}"; mkdir -p "$d" && cp "$1" "$d" shell script to all xls files, that is, first create the target directory and copy the file at destination.

    If you have a lot of files and performance issues you can try to optimize a bit with:

    find . -type f -name '*.xls' -exec sh -c \
    'for f in "$@"; do d="newDir/${f%/*}"; mkdir -p "$d" && cp "$f" "$d"; done' sh {} +
    

    This second version processes the files by batches and thus spawns less shells.