Comment gérer correctement l’extension des caractères génériques dans un script shell bash?

#!/bin/bash hello() { SRC=$1 DEST=$2 for IP in `cat /opt/ankit/configs/machine.configs` ; do echo $SRC | grep '*' > /dev/null if test `echo $?` -eq 0 ; then for STAR in $SRC ; do echo -en "$IP" echo -en "\n\t ARG1=$STAR ARG2=$2\n\n" done else echo -en "$IP" echo -en "\n\t ARG1=$SRC ARG2=$DEST\n\n" fi done } hello $1 $2 

Ce qui précède est le script shell dont je fournis le chemin source (SRC) & desitnation (DEST). Cela a bien fonctionné quand je n’ai pas mis de chemin SRC avec un joker . Quand je lance ce script shell et que je donne “.pdf ou *” comme suit:

 root@ankit1:~/as_prac# ./test.sh /home/dev/Examples/*.pdf /ankit_test/as 

J’obtiens la sortie suivante:

 192.168.1.6 ARG1=/home/dev/Examples/case_Contact.pdf ARG2=/home/dev/Examples/case_howard_county_library.pdf 

Le DEST est / ankit_test /, mais DEST est également manipulé à cause de ‘*’. La réponse attendue est

 ARG1=/home/dev/Examples/case_Contact.pdf ARG2=/ankit_test/as 

Donc, si vous comprenez ce que j’essaie de faire, aidez-moi à résoudre ce problème. Je vous serai reconnaissant.

Merci d’avance!!!

Je dois savoir exactement comment j’utilise “* .pdf” dans mon programme un par un sans déranger DEST.

Votre script a besoin de plus de travail. Même après avoir échappé au caractère générique, vous n’obtiendrez pas votre réponse attendue. Tu auras:

 ARG1=/home/dev/Examples/*.pdf ARG2=/ankit__test/as 

Essayez plutôt la suivante:

 for IP in `cat /opt/ankit/configs/machine.configs` do for i in $SRC do echo -en "$IP" echo -en "\n\t ARG1=$i ARG2=$DEST\n\n" done done 

Exécutez le comme ceci:

 root@ankit1:~/as_prac# ./test.sh "/home/dev/Examples/*.pdf" /ankit__test/as 

Le shell développera les caractères génériques à moins que vous ne leur échappiez, par exemple si vous avez

 $ ls one.pdf two.pdf three.pdf 

et lancez votre script en tant que

 ./test.sh *.pdf /ankit__test/as 

ce sera le même que

 ./test.sh one.pdf two.pdf three.pdf /ankit__test/as 

ce qui n’est pas ce que vous attendez. Faire

 ./test.sh \*.pdf /ankit__test/as 

devrait marcher.

Si vous le pouvez, changez l’ordre des parameters transmis à votre script shell comme suit:

 ./test.sh /ankit_test/as /home/dev/Examples/*.pdf 

Cela rendrait votre vie beaucoup plus facile puisque la partie variable se déplace à la fin de la ligne. Ensuite, le script suivant fera ce que vous voulez:

 #!/bin/bash hello() { SRC=$1 DEST=$2 for IP in `cat /opt/ankit/configs/machine.configs` ; do echo -en "$IP" echo -en "\n\t ARG1=$SRC ARG2=$DEST\n\n" done } arg2=$1 shift while [[ "$1" != "" ]] ; do hello $1 $arg2 shift done 

Il vous manque également un dernier “fait” pour fermer votre boucle externe.

OK, cela semble faire ce que vous voulez:

 #!/bin/bash hello() { SRC=$1 DEST=$2 while read IP ; do for FILE in $SRC; do echo -e "$IP" echo -e "\tARG1=$FILE ARG2=$DEST\n" done done < /tmp/machine.configs } hello "$1" $2 
  1. Vous devez toujours échapper à tous les caractères génériques lorsque vous appelez le script
  2. Les guillemets sont nécessaires lorsque vous invoquez la fonction hello , sinon le simple fait d'évaluer $1 entraîne l'extension du caractère générique, mais nous ne voulons pas que cela se produise tant que $SRC n'est pas affecté dans la fonction

Voici ce que j’ai imaginé:

 #!/bin/bash hello() { # DEST will contain the last argument eval DEST=\$$# while [ $1 != $DEST ]; do SRC=$1 for IP in `cat /opt/ankit/configs/machine.configs`; do echo -en "$IP" echo -en "\n\t ARG1=$SRC ARG2=$DEST\n\n" done shift || break done } hello $* 

Au lieu de ne transmettre que deux parameters à la fonction hello (), nous allons transmettre tous les arguments obtenus par le script.

Dans la fonction hello (), nous atsortingbuons d’abord l’argument final à la variable DEST. Ensuite, nous parcourons tous les arguments, en assignant chacun à SRC, et exécutons les commandes que nous voulons en utilisant les arguments SRC et DEST. Notez que vous pouvez placer des guillemets autour de $ SRC et $ DEST au cas où ils contiennent des espaces. Nous arrêtons la boucle lorsque SRC est identique à DEST car cela signifie que nous avons atteint le dernier argument (la destination).

Pour les fichiers d’entrée multiples utilisant un caractère générique tel que * .txt, j’ai trouvé que cela fonctionnait parfaitement, pas besoin d’échapper. Il devrait fonctionner comme une application bash native comme “ls” ou “rm”. Cela n’a pas été documenté à peu près partout, puisque j’ai passé une bonne partie de 3 jours à essayer de le comprendre, j’ai décidé de le poster pour les futurs lecteurs.

Répertoire contient les fichiers suivants (sortie de ls)

 file1.txt file2.txt file3.txt 

Exécuter le script comme

 $ ./script.sh *.txt 

Ou même comme

 $ ./script.sh file{1..3}.txt 

Le script

 #!/bin/bash # store default IFS, we need to temporarily change this sfi=$IFS #set IFS to $'\n\' - new line IFS=$'\n' if [[ -z $@ ]] then echo "Error: Missing required argument" echo exit 1 fi # Put the file glob into an array file=("$@") # Now loop through them for (( i=0 ; i < ${#file[*]} ; i++ )); do if [ -w ${file[$i]} ]; then echo ${file[$i]} " writable" else echo ${file[$i]} " NOT writable" fi done # Reset IFS to its default value IFS=$sfi 

Le résultat

 file1.txt writable file2.txt writable file3.txt writable 

La clé commutait temporairement l'IFS (Internal Field Separator). Vous devez vous assurer de stocker ceci avant de changer, puis de le changer lorsque vous en avez terminé avec la démonstration ci-dessus.

Vous avez maintenant une liste de fichiers étendus ( avec des espaces échappés ) dans le tableau [] que vous pouvez ensuite parcourir. J'aime cette solution la meilleure, la plus facile à programmer et la plus simple pour les utilisateurs.

Il n’y a pas besoin de lancer un shell pour regarder le $? variable, vous pouvez l’évaluer directement.

Ce devrait juste être:

 if [ $? -eq 0 ]; then 

Tu cours

 ./test.sh /home/dev/Examples/*.pdf /ankit_test/as 

et votre shell interactif étend le caractère générique avant que le script ne l’obtienne. Vous devez juste citer le premier argument lorsque vous le lancez, comme dans

 ./test.sh "/home/dev/Examples/*.pdf" /ankit_test/as 

et ensuite, dans votre script, citez “$ SRC” partout où vous voulez littéralement les choses avec des caractères génériques (par exemple, lorsque vous faites echo $SRC , utilisez plutôt echo "$SRC" ) et laissez-le Fondamentalement, placez toujours des guillemets autour des choses qui pourraient contenir des métacaractères de shell à moins que vous ne vouliez interpréter les métacaractères. 🙂