[bash] Variable indirection
Bonjour,
J'ai quelques questions sur les "variable indirection" (variables indirectes en français ??).
Ma version de bash :
GNU bash, version 4.1.2(2)-release (x86_64-redhat-linux-gnu)
J'ai un script qui sert à désarchiver plusieurs fichiers qui se trouvent dans différentes archives (et à faire d'autres choses aussi).
Les fichiers à désarchiver sont à passer en argument du script.
Dans fichiers_ABCD.tar.gz, il y aura des fichiers se nommant par exemple :
fichier_ABCD_000001.xml
fichier_ABCD_000002.xml
etc...
Dans fichiers_1234.tar.gz, il y aura des fichiers se nommant par exemple :
fichier_1234_000001.xml
fichier_1234_000002.xml
etc...
Voici le script (enfin une partie) :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| #!/bin/bash
CR=0
for fic
do
# Test important suite à l'utilisation d'eval plus bas
( LC_COLLATE=C; [[ $fic != fichier_[A-Z0-9][A-Z0-9][A-Z0-9][A-Z0-9]_[0-9][0-9][0-9][0-9][0-9][0-9].xml ]] ) && {
echo "ERREUR - Nom de fichier incorrect ($fic)"
CR=1
}
(( CR )) && continue
code=${fic:8:4}
[[ ${liste_codes[@]} != *$code* ]] && liste_codes+=("$code") # Tableau contenant la liste des codes
# Ajout d'un élément dans le tableau fics_ABCD si par exemple $code == ABCD
# Il est important d'avoir bien verifié la valeur de $code
eval fics_$code'+=("$fic")'
done
(( CR )) && exit 1
rep_extract_fics=/destination/des/fichiers
for code in "${liste_codes[@]}"
do
echo; echo "Désarchivage des fichiers pour $code..."
nom_liste=fics_$code[@] # Ex : si $code == ABCD, alors $nom_liste vaudra fics_ABCD[@]
archive=/emplacement/des/archives/${code}/fichiers_${code}.tar.gz # Emplacement de l'archive
echo ">>> Extraction des fichiers depuis $archive..."
tar xvf "$archive" -C "$rep_extract_fics" "${!nom_liste}" # "${!nom_liste}" équivaut à "${fics_ABCD[@]}" si $code == ABCD
(($?)) && { echo "ERREUR - Echec de l'extraction des fichier_${code}_*.xml"; exit 1;}
echo "Extraction OK"
echo ">>> Mise à jour des droits des fichiers désarchivés pour $code..."
eval 'chmod 660 "${'"$nom_liste"'/#/$rep_extract_fics/}"' # Utilisation de eval car "${!nom_liste/#/$rep_extract_fics/}" rajoute $rep_extract_fics/ seulement devant le premier element du tableau
(($?)) && { echo "ERREUR - Echec de la mise à jour des droits des fichiers désarchivés"; exit 1;}
echo "Mise à jour des droits OK"
done |
eval fics_$code'+=("$fic")' : peut-on remplir le tableau, dont le nom n'est donc pas défini directement, sans utiliser eval ?
tar xvf "$archive" -C "$rep_extract_fics" "${!nom_liste}" : fonctionne comme je m'y attendais ; si $nom_liste == fics_ABCD[@], "${!nom_liste}" me donne bien tous les éléments, comme si j'avais utilisé directement "${fics_ABCD[@]}"
Par contre, ça "bug" pour ce genre de chose :
Code:
1 2 3 4
| $ fics_ABCD=(aa bb cc dd)
$ nom_liste=fics_ABCD[@]
$ echo "${!liste#?}"
a bb cc dd |
Je m'attendais plutôt au résultat a b c d, comme si j'avais tapé echo "${fics_ABCD[@]#?}"
Code:
1 2
| $ echo "${!liste/#/X}"
Xaa bb cc dd |
Je m'attendais plutôt au résultat Xaa Xbb Xcc Xdd, comme si j'avais tapé echo "${fics_ABCD[@]/#/X}"
C'est un bug ou c'est logique ce fonctionnement ?