Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 15/06/2014, à 17:03

sylvanux

RESOLU Exercice de Mathieu Nebra (reprenez le controle avec linux)

Bonjour

Voila je suis en train de lire le livre de Mathieu Nebra et je coince sur un exercice qu'il faut faire. C'est un script en shell qui demande à l'utilisateur d'entrer un *.txt après le script et ca renomme tous les fichiers texte avec un "-old".
Si le *.txt n'est pas rentré il faut rentrer les fichiers à renommé.

Voici mon script :

#!/bin/bash


if [ $1 = ".txt" ]; then

        for fichier in `ls *.txt`
        do
        mv $fichier $fichier-old

elif [ -z $1 ]; then

        read -p 'Entrez le nom du ou des fichiers à modifier' fichier1 fichier2 fichier3
        mv fichier1 fichier1-old
        mv fichier2 fichier2-old
        mv fichier3 fichier3-old
else

        echo 'fin du programe'

fi

Voila quand j'exécute le script j'ai ce message

./essai_variable: ligne 10: Erreur de syntaxe près du symbole inattendu « elif »
./essai_variable: ligne 10: `elif [ -z $1 ]; then'

Je ne sais pas quoi faire.
Sinon j'ai une autre question plus complexe, j'ai entré 3 fichiers a renommé mais comment peut on faire si on ne connait pas le nombre de fichier à l'avance et ainsi entrer un nombre n de variables??

Merci

Dernière modification par sylvanux (Le 17/06/2014, à 19:02)

Hors ligne

#2 Le 15/06/2014, à 17:20

melixgaro

Re : RESOLU Exercice de Mathieu Nebra (reprenez le controle avec linux)

salut,

déjà cette ligne n'est pas bonne (ça marche, mais c'est pas l'idéal)

for fichier in `ls *.txt`

à remplacer par

for fichier in *.txt

Et il faut fermer la boucle for avec done (c'est ce qui signifie l'erreur : le shell s'attend à trouver done et trouve elif). Donc ça devient

for fichier in *.txt
do
   mv -v "${fichier}" "${fichier}-old"
done

Explication :
---------------
- L'expansion de *.txt se fera toute seule et tu n'auras pas de problèmes si des noms de fichiers ont des espaces, contrairement à la ligne que tu as écrite.
- Prendre l'habitude d'écrire les noms de variables avec les accolades. Par exemple, imagine au lieu d'ajouter "-old" tu veux ajouter "1" derrière le nom du fichier. Avec $fichier1, le shell va chercher une variable qui s'appelle fichier1, il ne va pas comprendre que c'est la variable fichier à laquelle il faut ajouter 1 après expansion. Par contre, avec ${fichier}1, il n'y a pas d'ambiguité.
- Prendre l'habitude de mettre des guillemets anglais " autour des variables qui contiennent des chaînes de caractères alphanumériques, en particulier si des espaces risquent d'être présent.

Fais le test en créant un fichier nommé 'nom avec des espaces.txt' et essaye la boucle for avec ta syntaxe et la mienne.

Dernière modification par melixgaro (Le 15/06/2014, à 17:22)


Linux depuis ~2007. Xubuntu seulement.

Hors ligne

#3 Le 15/06/2014, à 20:47

pingouinux

Re : RESOLU Exercice de Mathieu Nebra (reprenez le controle avec linux)

Bonsoir,

sylvanux #1 a écrit :

Sinon j'ai une autre question plus complexe, j'ai entré 3 fichiers a renommé mais comment peut on faire si on ne connait pas le nombre de fichier à l'avance et ainsi entrer un nombre n de variables??

En rentrant les fichiers un par un :

while read -p 'Entrez le nom du fichier à modifier : ' fichier
do
   [ "$fichier" ] || break
   mv "$fichier" "$fichier-old"
done

Hors ligne

#4 Le 17/06/2014, à 17:11

sylvanux

Re : RESOLU Exercice de Mathieu Nebra (reprenez le controle avec linux)

Voila maintenant je ne vois pas ce qui cloche

#!/bin/bash


if [ $1 = '.txt' ] && [ $# -ge 1 ]
then
        for fichier in *.txt
        do
        mv -v "${fichier}" "${fichier}-old"
done

elif [ -z $1 ] 
then
         read -p 'Entrez le nom du fichier à modifier : ' fichier
        mv  "$fichier" "$fichier-old" 
else

        echo 'fin du programme'
fi

Il m'affiche le message d'erreur suivant :

./essai_variable: ligne 4 : [: = : opérateur unaire attendu

Est-ce que le shell attends une valeur, si je rentre .txt le programme fonctionne, mis à part le message de fin qui ne s'affiche pas??
La réponse doit être toute bête mais n'ayant pas assez d'expérience je vois pas!!!

Hors ligne

#5 Le 17/06/2014, à 17:59

pingouinux

Re : RESOLU Exercice de Mathieu Nebra (reprenez le controle avec linux)

Comme te l'a indiqué melixgaro en #2, il faut mettre des " " autour des variables quand tu les utilises (utile si elles contiennent des espaces ou sont vides) :

if [ "$1" = '.txt' ] && [ $# -ge 1 ]
............................
elif [ -z "$1" ]

Ton script n'affiche le message de fin que s'il est appelé avec un paramètre non nul et différent de .txt.

Tu pourrais aussi faire ceci :

#!/bin/bash

[ $# = 0 ] && echo 'Donner au moins un nom de fichier'

for fichier in "$@"
do
   echo mv -v "${fichier}" "${fichier}-old"
done

echo 'fin du programme'

En appelant le script ainsi :

./le_script *.txt

ou

./le_script fichier1 fichier2

Hors ligne

#6 Le 17/06/2014, à 19:06

sylvanux

Re : RESOLU Exercice de Mathieu Nebra (reprenez le controle avec linux)

Dis moi à quoi correspond exactement ce symbole : $@ ???

Hors ligne

#7 Le 17/06/2014, à 19:19

pingouinux

Re : RESOLU Exercice de Mathieu Nebra (reprenez le controle avec linux)

"$@" est remplacé par la liste des paramètres d'appel du script.

Voici un extrait de man bash :

Special Parameters
       The shell treats several parameters specially.  These parameters may only be referenced; assignment to them is not allowed.
       *      Expands  to the positional parameters, starting from one.  When the expansion occurs within double quotes, it expands to a sin‐
              gle word with the value of each parameter separated by the first character of the IFS  special  variable.   That  is,  "$*"  is
              equivalent  to  "$1c$2c...",  where c is the first character of the value of the IFS variable.  If IFS is unset, the parameters
              are separated by spaces.  If IFS is null, the parameters are joined without intervening separators.
       @   Expands to the positional parameters, starting from one.  When the  expansion  occurs  within  double  quotes,  each  parameter
              expands to a separate word.  That is, "$@" is equivalent to "$1" "$2" ...  If the double-quoted expansion occurs within a word,
              the expansion of the first parameter is joined with the beginning part of the original word, and  the  expansion  of  the  last
              parameter  is  joined  with the last part of the original word.  When there are no positional parameters, "$@" and $@ expand to
              nothing (i.e., they are removed).

Hors ligne