You can use tar
or cpio
or pax
(if any of these is available) to copy certain files, creating target directories as necessary. With GNU tar, to copy all regular files called *.txt
or README.*
underneath the current directory to the same hierarchy under ../destination
:
find . -type f \( -name '*.txt' -o -name 'README.*' \) |
tar -cf - -T - |
tar -xf - -C ../destination
With just find
, cp
, mkdir
and the shell, you can loop over the desired files with find
and launch a shell command to copy each of them. This is slow and cumbersome but very portable. The shell snippet receives the destination root directory as $0
and the path to the source file as $1
; it creates the destination directory tree as necessary (note that directory permissions are not preserved by the code below) then copies the file. The snippet below works on any POSIX system and most BusyBox installations.
find . -type f \( -name '*.txt' -o -name 'README.*' \) -exec sh -c '
mkdir -p "$0/${1%/*}";
cp -p "$1" "$0/$1"
' ../destination {} \;
You can group the sh
invocations; this is a little complicated but may be measurably faster.
find . -type f \( -name '*.txt' -o -name 'README.*' \) -exec sh -c '
for x; do
mkdir -p "$0/${x%/*}";
cp -p "$x" "$0/$x";
done
' ../destination {} +
If you have bash ≥4 (I don't know whether Git Bash is recent enough), you don't need to call find
, you can use the **
glob pattern to recurse into subdirectories.
shopt -s globstar extglob
for x in **/@(*.txt|README.*); do
mkdir -p "../destination/${x%/*}"
cp -p -- "$x" "../destination/$x"
done
bash
available? – enzotib Mar 05 '12 at 16:42robocopy
can do that directly on windows (robocopy /S sourcedir targetdir *blah*
) – Mat Mar 05 '12 at 16:54