Modificando padrões globbing zsh para usar com cp

Modificando padrões globbing zsh para usar com cp

Estou tentando escrever um script para copiar arquivos recursivamente de uma pasta específica A.extn, exceto files B/*.extne C/*onde Be Csão diretórios e extné apenas uma extensão genérica. Isto é o que eu tenho:

#!/usr/local/bin/zsh
setopt EXTENDED_GLOB
TMPDIR=/tmp/test

cp -pR $(dirname $0)/**~(*.foo/*|*/bar.txt|*.abc|qux.txt) $TMPDIR

No entanto, isso não nega o padrão conforme o esperado. Acho que sei por quê - embora o padrão esteja correto (como visto em echo), cp -Rnão está ciente do padrão e entra em um diretório que "não deveria" e, uma vez lá, o padrão não é mais válido.

Como modifico o acima para fazer o que quero? Eu acho que é possível com findand xargs, mas estou atraído pela clareza do que foi dito acima e preferiria algo semelhante (mas se for a maneira errada de fazer isso, ficaria perfeitamente feliz com uma solução diferente).

Responder1

Você está certo de que o padrão é expandido antes de cpser executado, portanto, é desconhecido para esse comando.

Você pode conseguir o que deseja usando a --parentsopção em cpvez de -R. Isso copiará apenas os arquivos que correspondem ao seu padrão, mas usará o nome completo do caminho fornecido, em vez de apenas o nome do arquivo final.

Mas esta opção não é portátil. AFAIK, é suportado apenas pela versão GNU do cp.

Responder2

Seu padrão pode excluir os arquivos que você não deseja copiar, mas não exclui os diretórios que os contêm, e você disse cppara copiar recursivamente. Portanto, os arquivos são copiados de qualquer maneira. Pior que isso, se você tiver uma árvore de origem como

foo
foo/bar.txt
hello
hello/world
hello/world/wibble.txt

então o padrão se expande foo hello hello/world hello/world/wibble.txtpara que você tenha esses arquivos em $TMPDIR:

foo
foo/bar.txt
hello
hello/world
hello/world/wibble.txt
wibble.txt
world
world/wibble.txt

Isso não tem nada a ver com o padrão “não ser mais válido”. O padrão é expandido pelo shell, cpsó vê a lista de arquivos.

Você precisa usar uma ferramenta de cópia que possa excluir arquivos enquanto faz a travessia recursiva.

Você pode usar o zcp para isso, mas ele não copiará os diretórios e não criará diretórios de destino automaticamente. A ferramenta mais fácil para este trabalho é o rsync. Pax é outra opção.

rsync -a --exclude='*.foo/*' --exclude='bar.txt' --exclude='*.abc' --exclude='/qux.txt' $(dirname $0) $TMPDIR

informação relacionada