Como excluo uma extensão específica da cópia recursiva de arquivos?

Como excluo uma extensão específica da cópia recursiva de arquivos?

Quero copiar todos os arquivos e subdiretórios, exceto o arquivo de dados denominado *.data, para um diretório de destino.

 [ichen@ui01 sub_test]$ ls
a.cxx  a.data  subdir
[ichen@ui01 sub_test]$ ls subdir/
sub_a.cxx  sub_a.data

Você pode ver que existem 2 arquivos de dados no diretório externo e no subdiretório, respectivamente. Eu usei este comando:

[ichen@ui01 sub_test]$ cp -r !(*.data) ../destination_dir/

pretendia copiar todos os arquivos exceto o *.data para o destino, mas não funciona no subdiretório:

  [ichen@ui01 destination_dir]$ ls
a.cxx  subdir
[ichen@ui01 destination_dir]$ ls subdir/
sub_a.cxx  sub_a.data

Você pode ver acima que este comando funciona apenas no primeiro diretório, como posso fazer com que funcione em todos os subdiretórios?

Responder1

Você não especifica em sua pergunta se é um requisito preservar a estrutura de diretórios na cópia ou se você só precisa de uma cópia dos arquivos. Para simplesmente copiar todos os arquivos não nomeados *.data você pode usar isto:

find . -type f ! -name '*.data' | xargs cp -t ../destination_dir/

Por outro lado, se você quiser preservar a estrutura de diretórios, você pode usar algo assim:

for file in `find . ! -name '*.txt' | sed 's/^.\///'`; do if [ -d "./$file" ]; then mkdir -p "../destination_dir/$file"; else cp "./$file" "../destination_dir/$file"; fi; done

Não tenho certeza se existe uma maneira mais simples de fazer isso, mas este comando faz o seguinte:

Encontre todos os arquivos e pastas no diretório atual ou suas subpastas que não correspondem a *.data e, em seguida, para cada um:

Teste se o arquivo é um diretório, se for um diretório correspondente no diretório de destino ou se for um arquivo, ele o copia para o destino.

Editar: Adicionando versão do shell script:

#!/bin/bash

# Disable shell glob expansion within the script
# Required to stop bash from expndinging the glob in $1
set -f

for file in `find . ! -name $1 | sed 's/^.\///'`
  do if [ -d "./$file" ]; then
    mkdir -p "$2/$file"
  else
    cp "./$file" "$2/$file"
fi
done

informação relacionada