Sobre a transmissão de argumentos para programas através de variáveis de matriz

3

NB: embora a pergunta abaixo apresente rsync , não é uma pergunta sobre rsync ; é uma questão sobre matrizes zsh.

Se eu inicializar a variável EXCLUDES como esta

EXCLUDES=( --exclude=/foo --exclude=/bar --exclude=/baz )

então, quando eu executo o comando

rsync -a $EXCLUDES / /some/target

... então, vejo que /foo , /bar e /baz não são realmente copiados para /some/target .

Mas agora, suponha que EXCLUDE_ITEMS seja algo assim

EXCLUDE_ITEMS=( /foo /bar /baz )

... e inicializo EXCLUDE assim

EXCLUDES=()
for item in $EXCLUDE_ITEMS
do
    EXCLUDES+=( "--exclude='$item'" )
done

... ou assim

EXCLUDES=( $(for item in $EXCLUDE_ITEMS; do echo "--exclude='$item'"; done) )

... então, em qualquer caso, depois que eu corro

rsync -a $EXCLUDES / /some/target

... agora eu descubro que os diretórios excluídos não foram excluídos da transferência.

Como as linhas de comando (conforme digitadas no terminal) são todas idênticas, devo concluir que existe uma diferença entre o EXCLUDES explicitamente inicializado daqueles que são inicializados pela iteração acima de EXCLUDE_ITEMS , mas não consigo descobrir o que é isso.

Como posso inicializar EXCLUDE dos itens em EXCLUDE_ITEMS para que o último seja excluído quando eu executo

rsync -a $EXCLUDES / /some/target

PS: Na verdade, se eu corro

eval "rsync -a $EXCLUDES / /some/target"

... onde EXCLUDES foi inicializado em qualquer uma das formas for -loop-based mostradas acima, então os diretórios nomeados em EXCLUDES são de fato excluídos, conforme desejado.

    
por kjo 06.03.2016 / 21:07

1 resposta

3

O problema é que, escrevendo "--exclude='$item'" , você está colocando aspas simples no padrão de exclusão. Então você está excluindo '/foo' e assim por diante, mas provavelmente você não tem arquivos com nomes começando e terminando com aspas simples.

Você precisa escrever

EXCLUDES+=( "--exclude=$item" )

ou, como isso é zsh, você não precisa de aspas duplas: apenas escreva

EXCLUDES+=( --exclude=$item )

ou, como isso é zsh, você não precisa de um loop: basta usar o opção de expansão do parâmetro ^ :

rsync -a --exclude=$^EXCLUDE_ITEMS …

Em ksh ou bash, você precisaria do loop e aspas duplas:

EXCLUDES=()
for item in "${EXCLUDE_ITEMS[@]}";  do
  EXCLUDES+=( "--exclude=$item" )
done
rsync -a "${EXCLUDES[@]}" …
    
por 06.03.2016 / 21:14