Je débute tout juste dans le script avec bash et je tombe sur un problème que je n'arrive pas à résoudre par manque d'entraînement...
J'essaye de faire un script très simple qui crée 3 .txt et qui les supprime tout de suite après si ils correspondent bien au premier paramètre passé avec le script (ici *.txt)
Voici le code :
for i in `seq 1 3`;
do
touch $i.txt
done
if [ -z "$1" ]
then
echo "you must enter one param"
exit 1
else
echo "expected file type : $1"
for file in `ls`
do
echo $file
if [ $1 = $file ]
then
echo "$file correponds to the expected the $1 file type"
rm $file
else
echo "$file doesn't correpond to the expected the $1 file type"
fi
done
fi
l'erreur vient de la ligne : if [ $1 = $file ]
Je ne sais pas comment écrire pour qu'il comprenne que chaque file qui a une terminaison .txt soit pris en compte.
Voici l'erreur :
expected file type : *.txt
1.txt
./bash_summary.sh: line 46: [: too many arguments
1.txt doesn't correpond to the expected the *.txt file type
2.txt
./bash_summary.sh: line 46: [: too many arguments
2.txt doesn't correpond to the expected the *.txt file type
3.txt
./bash_summary.sh: line 46: [: too many arguments
3.txt doesn't correpond to the expected the *.txt file type
bash_summary.sh
./bash_summary.sh: line 46: [: too many arguments
bash_summary.sh doesn't correpond to the expected the *.txt file type
touch est une commande externe inutile : une redirection vide crée un fichier vide s'il n'existe pas.
ls ne doit pas être utilisé dans un script; il faut utiliser le Développement des chemins (cf. le man)
il faut toujours mettre mettre les Remplacements de paramètres (développements de variables) entre guillemets. TOUJOURS.
enfin, attention, s'il y a des fichiers .txt dans le répertoire courant, $1 correspondra au premier fichier trouvé (par ordre alphabétique), parce que le shell va développer l'astérisque. il faut donc protéger cet astérisque.
Validez la réponse utile « Un problème clairement exposé est à moitié résolu. » Pas de MP technique
touch est une commande externe inutile : une redirection vide crée un fichier vide s'il n'existe pas.
ls ne doit pas être utilisé dans un script; il faut utiliser le Développement des chemins (cf. le man)
il faut toujours mettre mettre les Remplacements de paramètres (développements de variables) entre guillemets. TOUJOURS.
enfin, attention, s'il y a des fichiers .txt dans le répertoire courant, $1 correspondra au premier fichier trouvé (par ordre alphabétique), parce que le shell va développer l'astérisque. il faut donc protéger cet astérisque.
Merci beaucoup pour vos conseils !
Cependant je ne suis que débutant et je comprends l'idée que vous voulez me faire passer mais je ne sais pas comment l'appliquer dans le script, pouvez-vous s'il vous plaît me montrer une petite version corrigée de mon exemple ?
mets des guillemets autour des Remplacements de paramètres
- Edité par dantonq il y a environ 1 heure
J'ai modifié pour les guillemets, l'erreur a disparu mais le script ne fait pas ce qui est attendu...
for i in `seq 1 3`;
do
touch $i.txt
done
if [ -z "$1" ]
then
echo "you must enter one param"
exit 1
else
echo "expected file type : '$1'"
for file in `ls`
do
echo "$file"
if [ "$1" = "$file" ]
then
echo "$file correponds to the expected the '$1' file type"
rm "$file"
else
echo "$file doesn't correpond to the expected the '$1' file type"
fi
done
fi
expected file type : '*.txt'
1.txt
1.txt doesn't correpond to the expected the '*.txt' file type
2.txt
2.txt doesn't correpond to the expected the '*.txt' file type
3.txt
3.txt doesn't correpond to the expected the '*.txt' file type
bash_summary.sh
bash_summary.sh doesn't correpond to the expected the '*.txt' file type
Que dois-je changer concernant le touch, le ls et la protection de l'astérisque ?
le seq aussi peut être changer par for i in {1..3}
le test tente de comparer 1.txt (par exemple) avec *.txt. à moins qu'un fichier nommé *.txt soit trouvé, il n'y aura pas de correspondance.
*.txt peut être développer par le shell en les fichiers et répertoires se terminant par .txt dans le répertoire courant, mais ce n'est pas une expression de comparaison telle qu'une regex. pas avec test. ça peut fonctionner avec [[...
mais, es-tu sûr d'avoir bien compris l'énoncé de l'exercice ? l'argument passé doit être *.txt ? ou seulement l'extension ?
il existe un Remplacement de paramètres qui permet de ne récupérer (pour faire simple) que la dernière partie d'une variable après un motif donné...
-- NB: dans un test, l'élément à comparer doit être à gauche, et le motif à droite.
- Edité par dantonq 19 janvier 2021 à 11:20:40
Validez la réponse utile « Un problème clairement exposé est à moitié résolu. » Pas de MP technique
le seq aussi peut être changer par for i in {1..3}
le test tente de comparer 1.txt (par exemple) avec *.txt. à moins qu'un fichier nommé *.txt soit trouvé, il n'y aura pas de correspondance.
*.txt peut être développer par le shell en les fichiers et répertoires se terminant par .txt dans le répertoire courant, mais ce n'est pas une expression de comparaison telle qu'une regex. pas avec test. ça peut fonctionner avec [[...
mais, es-tu sûr d'avoir bien compris l'énoncé de l'exercice ? l'argument passé doit être *.txt ? ou seulement l'extension ?
il existe un Remplacement de paramètres qui permet de ne récupérer (pour faire simple) que la dernière partie d'une variable après un motif donné...
-- NB: dans un test, l'élément à comparer doit être à gauche, et le motif à droite.
- Edité par dantonq il y a environ 1 heure
jo_link_noir a écrit:
> Que dois-je changer concernant le (1) touch, le (2) ls et la (3) protection de l'astérisque ?
touch file -> > file
ls -> * (on utilise du globbing classique)
cmd *.txt -> cmd '*.txt'/cmd \*.txt, mais à priori c'est déjà le cas puisque le message affiche bien *.txt.
J'ai essayé de suivre vos conseils pour améliorer le code (j'ai changé > file par > file car je le comprenais mieux comme ça et sur un forum il était dit que c'était pareil) mais je n'arrive toujours pas au résultat voulu.
Voici le code :
for i in {1..3};
do
> $i.txt
done
if [ -z "$1" ]
then
echo "you must enter one param"
exit 1
else
echo "expected file type : '$1'"
for file in *
do
echo "$file"
if [ "$file" = "$1" ]
then
echo "$file correponds to the expected the '$1' file type"
rm "$file"
else
echo "$file doesn't correpond to the expected the '$1' file type"
fi
done
fi
je l'ai expliqué dans mon précédent message, je te le montre (ne t'occupes pas des set, c'est une option de débuggage) :
$ comp='*.txt'; file=1.txt
$ set -x; test "$file" = "$comp"; set +x
+ test 1.txt = '*.txt'
+ set +x
on voit que la comparaison se fait avec '*.txt', littéralement.
je propose :
test "${file##*.}" = "${1##*.}"
qui comme je l'ai indiqué ne retient que la dernière partie après un motif, ici, un point.
PS: je n'ai pas participé à l'écriture du cours, et je ne vois pas l'intérêt de demander de passer *.txt comme argument : ce n'est pas utilisé, ça apporte des complications qu'on ne rencontre pas dans la pratique.
- Edité par dantonq 19 janvier 2021 à 14:16:47
Validez la réponse utile « Un problème clairement exposé est à moitié résolu. » Pas de MP technique
je l'ai expliqué dans mon précédent message, je te le montre (ne t'occupes pas des set, c'est une option de débuggage) :
$ comp='*.txt'; file=1.txt
$ set -x; test "$file" = "$comp"; set +x
+ test 1.txt = '*.txt'
+ set +x
on voit que la comparaison se fait avec '*.txt', littéralement.
je propose :
test "${file##*.}" = "${1##*.}"
qui comme je l'ai indiqué ne retient que la dernière partie après un motif, ici, un point.
PS: je n'ai pas participé à l'écriture du cours, et je ne vois pas l'intérêt de demander de passer *.txt comme argument : ce n'est pas utilisé, ça apporte des complications qu'on ne rencontre pas dans la pratique.
- Edité par dantonq il y a environ 4 heures
Merci beaucoup pour ton aide, j'ai enfin réussi ce que je voulais faire. J'ai cependant modifié le test avec du regex comme tu avais mis plus haut car je ne comprends pas bien ce que signifie test"${file##*.}"= "${1##*.}" . J'ai donc réalisé mon script comme ceci :
for i in {1..3};
do
> $i.txt
done
if [ ! -z "$1" ]
then
echo "no param expected"
exit 1
else
comp=".txt"
echo "expected file type : '$comp'"
for file in *
do
echo "$file"
if [[ $file =~ "$comp"$ ]]
then
echo "$file correponds to the expected the '$comp' file type"
rm "$file"
else
echo "$file doesn't correpond to the expected the '$comp' file type"
fi
done
fi
tu ne respectes pas ton énoncé, puisque tu n'utilises pas le paramètre positionnel du script.
bon. j'ai lu rapidement la partie du cours dont tu as donné le lien, il n'est pas très clair, et il montre des pratiques que je réprouve.
pas besoin de regex :
if [[ $file == $1 ]]
-- PS: ! -z ça veut dire -n c'est à dire que $1 existe
- Edité par dantonq 19 janvier 2021 à 19:38:18
Validez la réponse utile « Un problème clairement exposé est à moitié résolu. » Pas de MP technique
script bash débutant
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
Validez la réponse utile « Un problème clairement exposé est à moitié résolu. » Pas de MP technique
Validez la réponse utile « Un problème clairement exposé est à moitié résolu. » Pas de MP technique
Validez la réponse utile « Un problème clairement exposé est à moitié résolu. » Pas de MP technique
Validez la réponse utile « Un problème clairement exposé est à moitié résolu. » Pas de MP technique
Validez la réponse utile « Un problème clairement exposé est à moitié résolu. » Pas de MP technique