NB: bien que la question ci-dessous présente rsync
, ce n'est pas une question à propos de rsync
; c'est une question sur les arrays zsh.
Si j'initialise la variable EXCLUDES
comme ceci
EXCLUDES=( --exclude=/foo --exclude=/bar --exclude=/baz )
puis, lorsque j'exécute la command
rsync -a $EXCLUDES / /some/target
… alors je vois que /foo
, /bar
, et /baz
sont en effet pas copiés dans /some/target
.
Mais maintenant, supposons que EXCLUDE_ITEMS
soit quelque chose comme ça
EXCLUDE_ITEMS=( /foo /bar /baz )
… et j'initialise EXCLUDE comme ça
EXCLUDES=() for item in $EXCLUDE_ITEMS do EXCLUDES+=( "--exclude='$item'" ) done
… ou comme ça
EXCLUDES=( $(for item in $EXCLUDE_ITEMS; do echo "--exclude='$item'"; done) )
… alors dans les deux cas, après je cours
rsync -a $EXCLUDES / /some/target
… Je constate maintenant que les directorys exclus n'ont pas été exclus du transfert.
Puisque les lignes de commands (telles que tapées sur le terminal) sont toutes identiques, je dois conclure qu'il y a une différence entre les EXCLUDE_ITEMS
explicitement initialisés de ceux qui sont initialisés en itérant sur EXCLUDE_ITEMS
, mais je ne peux pas comprendre ce que c'est.
Comment puis-je initialiser EXCLUDE
partir des éléments dans EXCLUDE_ITEMS
afin que ce dernier soit effectivement exclu lorsque EXCLUDE_ITEMS
rsync -a $EXCLUDES / /some/target
PS: En fait, si je cours
eval "rsync -a $EXCLUDES / /some/target"
… où EXCLUDES
a été initialisé de l'une des façons indiquées ci-dessus, les directorys nommés dans EXCLUDES
sont en effet exclus, comme vous le souhaitez.
Le problème est qu'en écrivant "--exclude='$item'"
, vous "--exclude='$item'"
guillemets simples dans le model d'exclusion. Vous excluez donc '/foo'
et ainsi de suite, mais vous n'avez probablement pas de files avec des noms commençant et se terminant par des guillemets simples.
Vous devez écrire
EXCLUDES+=( "--exclude=$item" )
ou, puisque c'est zsh, vous n'avez pas besoin de guillemets doubles: écrivez juste
EXCLUDES+=( --exclude=$item )
ou, puisque c'est zsh, vous n'avez pas besoin d'une boucle: utilisez simplement l' option d'extension de paramètre ^
:
rsync -a --exclude=$^EXCLUDE_ITEMS …
Dans ksh ou bash, vous auriez besoin de la boucle et des guillemets doubles:
EXCLUDES=() for item in "${EXCLUDE_ITEMS[@]}"; do EXCLUDES+=( "--exclude=$item" ) done rsync -a "${EXCLUDES[@]}" …