Usando um arquivo de strings que precisam estar presentes nos nomes de diretório, um loop de shell sobre eles e rsync
(assumindo que queremos copiar do diretório na variável $source
e para o diretório na variável $target
):
while IFS= read -r string; do
rsync --archive --exclude='*DAT*/' --include='*/' --include="*$string*_Full/***" --exclude='*' \
--prune-empty-dirs "$source"/ "$target"
done <strings.txt
Quais são as opções para rsync
(o primeiro hit em qualquer um dos padrões de exclusão / inclusão é importante):
-
--archive
: copia propriedade, permissões, data e hora, etc. -
--exclude='*DAT*/'
: exclui qualquer diretório comDAT
em seu nome. -
--include='*/'
: considere todos os diretórios (exceto os excluídos pelo padrão anterior). Isso é necessário para quersync
atinja os diretórios reais nos quais você está interessado. -
--include="*$string*_Full/***"
: considere todos os diretórios que correspondem ao padrão fornecido e tudo abaixo desse diretório. Se$string
forparrot
, isso seria--include="*parrot*_Full/***"
. -
--exclude='*'
: não considere nada que ainda não esteja explicitamente incluído. -
--prune-empty-dirs
: não transfira diretórios que não tenham nada explicitamente incluído neles.
Se você quiser ver como rsync
avalia os padrões ao executá-lo, adicione -vv
à linha de comando rsync
.
Teste:
$ tree
.
|-- from
| '-- a
| '-- b
| |-- c_A_DATFull
| | '-- file
| |-- c_A_DAT_Full
| | '-- file
| |-- c_A_Full
| | '-- file
| |-- c_B_DATFull
| | '-- file
| |-- c_B_DAT_Full
| | '-- file
| |-- c_B_Full
| | '-- file
| |-- c_C_DATFull
| | '-- file
| |-- c_C_DAT_Full
| | '-- file
| '-- c_C_Full
| '-- file
'-- strings.txt
12 directories, 10 files
$ cat strings.txt
A
B
$ source=from
$ target=to
(executando o loop aqui)
$ tree
.
|-- from
[...]
'-- to
'-- a
'-- b
|-- c_A_Full
| '-- file
'-- c_B_Full
'-- file
17 directories, 12 files
Com uma única invocação de rsync
:
set -- --exclude='*DAT*/' --include='*/'
while IFS= read -r string; do
set -- "$@" --include="*$string*_Full/***"
done <strings.txt
set -- "$@" --exclude='*'
rsync --archive "$@" --prune-empty-dirs "$source"/ "$target"
Uma solução find
:
set --
while IFS= read -r string; do
set -- "$@" -o -name "*$string*_Full"
done <strings.txt
shift
# "$@" would now be something like
# -name *LP02323*_Full -o -name *Paaaf*_Full -o -name ...etc
find "$source" -type d '(' "$@" ')' ! -name '*DAT*' -exec sh -c '
source=$1; target=$2; shift 2
for pathname do
mkdir -p "$target/${pathname#$source}"
rsync --archive "$pathname"/ "$target/${pathname#$source}"
done' sh "$source" "$target" {} +
Isso usaria find
para gerar uma lista dos subdiretórios que você gostaria de copiar. Estes são dados para um pequeno script em linha que faz um loop sobre eles.
Em cada iteração do loop, o diretório correspondente no destino é criado (isso pressupõe cópia local) e o diretório é copiado usando rsync
.
Nunca use os nomes de caminho find
para canalizar para outro comando, a menos que você possa providenciar que os nomes dos caminhos sejam delimitados com segurança.
Relacionados: