Como copiar apenas arquivos correspondentes, preservando subdiretórios

6

Existe uma maneira de fazer isso: "Como posso copiar um subconjunto de arquivos de um diretório enquanto preservo a estrutura de pastas ", mas sem usar o rsync?

É possível ser feito usando somente cp, find e grep?

Eu tenho um shell muito limitado (ou seja, é um shell git no windows :(), então o rsync não é uma opção.

Eu sei que posso pegar o cygwin, mas fiquei imaginando o que posso fazer nessa situação limitada.

    
por Sunny 05.03.2012 / 16:48

2 respostas

8

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
    
por 05.03.2012 / 19:18
1

Você pode tentar algo assim:

ls | grep 2 | xargs -n1 -t -i cp -R {} ../testdirTwo/{}

Eu tentei isso no meu Linux e funciona. Note o parâmetro -R em cp, é para recursivo se você desejar. Observe também o parâmetro -i o xargs, ele irá inserir sua saída para onde você colocou {}. -é é apenas para ecoar o comando para stderr.

Minha estrutura de diretórios de teste ficou assim:

$ find .
.
./2
./2/f2
./1
./1/f1
./f1
./f2
    
por 05.03.2012 / 19:17