2017-01-16 1 views
1

j'ai écrit un script bash qui suit:Rsync et cite

SRC="dist_serv:$HOME/www/" 
DEST="$HOME/www/" 
OPTIONS="--exclude 'file.php'" 
rsync -Cavz --delete $OPTIONS $SRC $DEST 

rsync échoue et je ne peux pas comprendre pourquoi, bien qu'il semble être lié à la variable $ OPTIONS (cela fonctionne lorsque je retire il). J'ai essayé d'échapper à l'espace avec un backslash (parmi beaucoup d'autres choses) mais cela n'a pas fonctionné. Le message d'erreur est:

rsync: mkdir "/home/xxx/~/public_html/" failed: No such file or directory (2) 

J'ai essayé de citer la variable, ce qui jette une autre erreur ("option inconnue" sur mes variables $ OPTIONS):

rsync: --exclude 'xxx': unknown option 
rsync error: syntax or usage error (code 1) at main.c(1422) [client=3.0.6] 

Répondre

0

Vous ne devriez pas mettre $ devant des noms de variables lors de l'attribution de valeurs à ceux-ci. SRC est une variable, $SRC est la valeur à laquelle il se développe.

En outre, ~ n'est pas développé au chemin d'accès de votre répertoire personnel lorsque vous le placez entre guillemets. Il est généralement préférable d'utiliser $HOME dans les scripts car cette variable se comporte comme une variable, ce que ne fait pas ~.

Indiquez toujours des extensions variables:

rsync -Cavz --delete "$OPTIONS" "$SRC" "$DEST" 

moins qu'il n'y ait une raison de ne pas (il est très rare). Le shell va effectuer la séparation de mots sur eux autrement.

utilisateur @Fred indique que vous ne pouvez pas utiliser des guillemets doubles autour $OPTIONS (en dans les commentaires ci-dessous), mais il devrait être ok si vous utilisez OPTIONS='--exclude="file.php"' (notez le =).

+0

La variable OPTIONS ne peut pas être cité, car il contient deux mots, et citant les empêchera d'être partagé lors de l'interprétation de la commande (ils seront considérés comme une seule chaîne). Dans ce cas, ne pas citer OPTIONS fonctionnerait car il ne contient aucun espace, mais ce n'est pas une solution générale. – Fred

+0

oui bien sûr re: affectation variable! Modification de ma question ... – mrtnmgs

+1

@immicile Si vous pouviez également mentionner le message d'erreur exact que vous obtenez de 'rsync' dans la question, cela aiderait beaucoup! Ce – Kusalananda

0

Une technique que je trouve inestimable est l'utilisation de paramètres positionnels pour faciliter le travail avec la liste d'options. Lorsque vous placez des options dans une variable (telle que votre variable OPTIONS), vous devez trouver un moyen d'inclure des guillemets dans la valeur, et omettre des guillemets lorsque vous faites référence à la variable. Cela fonctionne, mais vous êtes toujours une faute de frappe d'un échec difficile à déboguer.

Essayez plutôt ce qui suit.

set -- -Cavz --delete 
set -- "[email protected]" --exclude "file.php" 
set -- "[email protected]" "dist_serv:~/www/" 
set -- "[email protected]" "~/www/" 
rsync "[email protected]" 

Bien sûr, dans ce cas, tout pourrait être sur la même ligne, mais dans de nombreux cas, il y aura des expressions conditionnelles de sorte que, par exemple, vous pouvez omettre une option donnée, ou sélectionnez les fichiers de différence pour travailler avec. La bonne chose est que vous utilisez toujours le même guillemet que vous utiliseriez sur une seule ligne de commande, le tout grâce à la magie de "[email protected]" qui évite de devoir référencer (ou citer) une variable spécifique.

Si les paramètres de position réels vous gênent, vous pouvez les placer dans des variables ou créer une fonction permettant d'isoler un contexte qui évite de les toucher là où ils sont importants.

J'utilise cette astuce tout le temps, et j'ai arrêté de retirer mes cheveux en raison de la citation causant des problèmes à l'intérieur des valeurs que je transmets comme paramètre aux commandes.

Un résultat similaire peut être obtenu en utilisant un tableau.

declare -a ARGUMENTS=() 
ARGUMENTS=(-Cavz --delete) 
ARGUMENTS+=(--exclude "file.php") 
ARGUMENTS+=("dist_serv:~/www/") 
ARGUMENTS+=("~/www/") 
rsync "${ARGUMENTS[@]}" 
+0

est une solution bien, mais mon script utilise déjà des paramètres de position et ils seront écrasés. – mrtnmgs

+0

j'ai ajouté une solution basée sur la baie qui produit des résultats similaires sans l'aide de paramètres de position. – Fred