Home > Net >  Copy all files with a certain extension from all subdirectories and preserving structure of subdirec
Copy all files with a certain extension from all subdirectories and preserving structure of subdirec

Time:11-30

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 \;

If an xls file is in: /s1/s2/ then ist 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.

CodePudding user response:

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.

CodePudding user response:

This should do:

# Ensure that newDir exists and is empty. Omit this step if you
# don't want it.
[[ -d newDir ]] && rm -r newDir && mkdir newDir

# Copy the xls files.
rsync -a --include='**/*.xls'  --include='*/' --exclude='*' . newDir

The trick here is the combination of include and exclude. By default, rsync copies everything below its source directory (. in your case). We change this by excluding everything, but also including the xls files.

In your example, newDir is itself a subdirectory of your working directory and hence part of the directory tree searched for copying. I would rethink this decision.

  • Related