Modificando padrões de globalização zsh para usar com cp

5

Estou tentando escrever um script para copiar arquivos recursivamente de uma determinada pasta, exceto os arquivos A.extn , B/*.extn e C/* , em que B e C são diretórios e extn é apenas algum genérico extensão. Isso é 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 faz a negação do padrão como esperado. Eu acho que sei por que - embora o padrão esteja correto (como visto em echo ), cp -R nã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 faço para modificar o acima para fazer o que eu quero? Eu acho que é possível com find e xargs , mas eu sou atraído para a clareza do acima e preferiria algo semelhante (mas se é a maneira errada de fazê-lo, eu ficaria perfeitamente feliz com um diferente solução).

    
por Lorem Ipsum 23.04.2013 / 01:29

2 respostas

2

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

Você pode conseguir o que deseja usando a opção --parents para cp em vez de -R . Isso só copiará os arquivos que corresponderem ao seu padrão, mas usará o nome do caminho completo conforme fornecido, em vez de apenas o nome do arquivo à direita.

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

    
por 23.04.2013 / 02:21
1

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 a cp para copiar recursivamente. Então os arquivos são copiados de qualquer maneira. Pior que isso, se você tem uma árvore fonte como

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

o padrão se expande para foo hello hello/world hello/world/wibble.txt , então você acaba com 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, cp apenas vê a lista de arquivos.

Você precisa usar uma ferramenta de cópia que possa excluir arquivos enquanto realiza 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
    
por 24.04.2013 / 03:48