En passant des arguments aux programmes via des variables de tableau

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[@]}" …