Você pode usar tar
ou cpio
ou pax
(se algum deles estiver disponível) para copiar determinados arquivos, criando diretórios de destino conforme necessário. Com o GNU tar, para copiar todos os arquivos regulares chamados *.txt
ou README.*
sob o diretório atual para a mesma hierarquia em ../destination
:
find . -type f \( -name '*.txt' -o -name 'README.*' \) |
tar -cf - -T - |
tar -xf - -C ../destination
Com apenas find
, cp
, mkdir
e o shell, você pode percorrer os arquivos desejados com find
e iniciar um comando shell para copiar cada um deles. Isso é lento e pesado, mas muito portátil. O fragmento de shell recebe o diretório raiz de destino como $0
e o caminho para o arquivo de origem como $1
; ele cria a árvore de diretórios de destino conforme necessário (observe que as permissões do diretório não são preservadas pelo código abaixo) e copia o arquivo. O trecho abaixo funciona em qualquer sistema POSIX e na maioria das instalações do BusyBox.
find . -type f \( -name '*.txt' -o -name 'README.*' \) -exec sh -c '
mkdir -p "$0/${1%/*}";
cp -p "$1" "$0/$1"
' ../destination {} \;
Você pode agrupar as invocações sh
; isso é um pouco complicado, mas pode ser mensuravelmente mais rápido.
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 {} +
Se você tem bash ≥4 (não sei se o Git Bash é recente o suficiente), não é necessário chamar find
, você pode usar o padrão **
glob para recorrer a subdiretórios.
shopt -s globstar extglob
for x in **/@(*.txt|README.*); do
mkdir -p "../destination/${x%/*}"
cp -p -- "$x" "../destination/$x"
done