Petite boucle difficile en sh
Résolu/Fermé
marine
-
25 nov. 2010 à 17:17
zipe31 Messages postés 36402 Date d'inscription dimanche 7 novembre 2010 Statut Contributeur Dernière intervention 27 janvier 2021 - 27 nov. 2010 à 14:15
zipe31 Messages postés 36402 Date d'inscription dimanche 7 novembre 2010 Statut Contributeur Dernière intervention 27 janvier 2021 - 27 nov. 2010 à 14:15
A voir également:
- Petite boucle difficile en sh
- Petite amie virtuelle en français - Accueil - Intelligence artificielle
- Télé samsung s'éteint et se rallume en boucle - Forum Téléviseurs
- Boucle excel sans macro - Forum Excel
- Fichier .sh - Forum Ubuntu
- Classez ces fichiers de la plus petite taille (1) à la plus grande (4). - Forum Bases de données
12 réponses
zipe31
Messages postés
36402
Date d'inscription
dimanche 7 novembre 2010
Statut
Contributeur
Dernière intervention
27 janvier 2021
6 418
25 nov. 2010 à 18:06
25 nov. 2010 à 18:06
Salut,
Je te propose une approche différente ;-)
On découpe la liste des arguments en 2 (avec "sed" en ajoutant un saut de ligne devant les lettres X ou Y lorsqu'elles sont précédées par un espace), puis on teste si la ligne commence par X ou par Y et en fonction on crée des répertoires ou des fichiers avec les arguments restants...
Ce qui donne :
;-))
Je te propose une approche différente ;-)
On découpe la liste des arguments en 2 (avec "sed" en ajoutant un saut de ligne devant les lettres X ou Y lorsqu'elles sont précédées par un espace), puis on teste si la ligne commence par X ou par Y et en fonction on crée des répertoires ou des fichiers avec les arguments restants...
Ce qui donne :
$ cat marine.sh #! /bin/bash #set -xv while read line do if [ "${line%% *}" = "X" ] then mkdir $(echo ${line#* }) else touch $(echo ${line#* }) fi done < <(echo "$@" | sed 's/ X\|Y/\n&/g') $ ./marine.sh X a b c d Y 1 2 3 4 $ ls 1 2 3 4 a/ b/ c/ d/ marine.sh* $ ls -l total 4 -rw-r--r-- 1 jp jp 0 2010-11-25 18:00 1 -rw-r--r-- 1 jp jp 0 2010-11-25 18:00 2 -rw-r--r-- 1 jp jp 0 2010-11-25 18:00 3 -rw-r--r-- 1 jp jp 0 2010-11-25 18:00 4 drwxr-xr-x 2 jp jp 40 2010-11-25 18:00 a/ drwxr-xr-x 2 jp jp 40 2010-11-25 18:00 b/ drwxr-xr-x 2 jp jp 40 2010-11-25 18:00 c/ drwxr-xr-x 2 jp jp 40 2010-11-25 18:00 d/ -rwxrw-r-- 1 jp jp 177 2010-11-25 17:59 marine.sh*
;-))
bonjour zipe et merci, mais je n'ai pas le droit d'utiliser sed, je souhaite rester sur mon approche qui me semble bien partie. tu as utilisé un read ça je peux mais j'ai essayé de l'utiliser dans mon script, sans succès.
comment attribuer à a variable y la valeur -d dans mon script?
comment attribuer à a variable y la valeur -d dans mon script?
zipe31
Messages postés
36402
Date d'inscription
dimanche 7 novembre 2010
Statut
Contributeur
Dernière intervention
27 janvier 2021
6 418
25 nov. 2010 à 19:04
25 nov. 2010 à 19:04
Il faudrait voir ton script en entier parce que là il y a des incohérences, genre la variable "$indice" n'est pas déclarée, d'où sort ce fameux "-d" ? etc. ;-(
Et ça tu y a droit :
Et ça tu y a droit :
$ echo "$@" X a b c d Y 1 2 3 4 $ echo -e "${@/Y/\nY}" X a b c d Y 1 2 3 4
non tu utilises des notions que je n'ai pas vu zipe, en fait je dois écrire un script tel que si je le lance comme ça:
./script.sh repertoire X 1 2 3 4 Y a b c d
il me crée les répertoires 1 2 3 4 si il lit X et crée les fichiers a b c d si il lit Y. MOn algo me semble pas mal parti, voici le script que j'ai commencé:
if [ $# -lt 1 ]
then
echo Il faut au moins un paramètre.
exit 1
fi
indice=1
y=""
mkdir $1
shift [1]
for i in "$@"
do
if [ "$i" = "X" ]
then
indice='expr $indice + 1'
$y=$i
elif [ "$i" != "X" ] && [ "$y" = "X" ] && [ "$i" != "Y" ]
then
mkdir repertoire/$indice
fi
done
qu'en dis tu?
./script.sh repertoire X 1 2 3 4 Y a b c d
il me crée les répertoires 1 2 3 4 si il lit X et crée les fichiers a b c d si il lit Y. MOn algo me semble pas mal parti, voici le script que j'ai commencé:
if [ $# -lt 1 ]
then
echo Il faut au moins un paramètre.
exit 1
fi
indice=1
y=""
mkdir $1
shift [1]
for i in "$@"
do
if [ "$i" = "X" ]
then
indice='expr $indice + 1'
$y=$i
elif [ "$i" != "X" ] && [ "$y" = "X" ] && [ "$i" != "Y" ]
then
mkdir repertoire/$indice
fi
done
qu'en dis tu?
zipe31
Messages postés
36402
Date d'inscription
dimanche 7 novembre 2010
Statut
Contributeur
Dernière intervention
27 janvier 2021
6 418
25 nov. 2010 à 20:30
25 nov. 2010 à 20:30
Ok, on va essayer de faire avec ce que tu connais et qui est autorisé...
;-))
$ cat marine2.sh #! /bin/bash #set -xv if [ $# -lt 1 ] then echo Il faut au moins un paramètre. exit 1 fi # Si le 1er param est "X" if [ "$1" = X ] # On décale then shift fi # Tant que le 1er paramètre est différent de "Y" while [ "$1" != "Y" ] do # On crée un répertoire au nom du paramètre mkdir "$1" # On décale shift done # Si le 1er param est "Y" if [ "$1" = Y ] # On décale then shift fi # Pour chaque paramètre restant, on crée un fichier à son nom for i in "$@" do # On crée un fichier à son nom touch "$i" done $ ls marine2.sh* $ ./marine2.sh a b c d Y 1 2 3 4 $ ls 1 2 3 4 a/ b/ c/ d/ marine2.sh* marine.sh* $
;-))
ok je vois zipe j'ai progressé dans ma compréhension grâce à toi mais je me suis très mal expliquée car lorsque j'appelle le script comme ça:
./script.sh repertoire X 1 2 3 4 Y a b c d
je dois tout créer dans le 1er paramètre qui est repertoire, ça je sais le corriger .
Mais mon script doit etre plus général, par exemple je peux l'appeler comme ça:
./script.sh repertoire X 1 2 3 4 Y a b c d X toto titi tata Y z e r t
Donc en gros il me faut une boucle générale qui prenne en compte tous les cas d'appels que je souhaite. Ma seule question est : est ce possible de faire ça dans une boucle générale?
Je veux juste que tu me répondes oui ou non, si c'est oui je tente d'écrire un code et je te montre le résultat ( car je veux bosser et j'ai horreur des codes tout faits si je n'y comprends rien ).
merci
./script.sh repertoire X 1 2 3 4 Y a b c d
je dois tout créer dans le 1er paramètre qui est repertoire, ça je sais le corriger .
Mais mon script doit etre plus général, par exemple je peux l'appeler comme ça:
./script.sh repertoire X 1 2 3 4 Y a b c d X toto titi tata Y z e r t
Donc en gros il me faut une boucle générale qui prenne en compte tous les cas d'appels que je souhaite. Ma seule question est : est ce possible de faire ça dans une boucle générale?
Je veux juste que tu me répondes oui ou non, si c'est oui je tente d'écrire un code et je te montre le résultat ( car je veux bosser et j'ai horreur des codes tout faits si je n'y comprends rien ).
merci
zipe31
Messages postés
36402
Date d'inscription
dimanche 7 novembre 2010
Statut
Contributeur
Dernière intervention
27 janvier 2021
6 418
25 nov. 2010 à 22:27
25 nov. 2010 à 22:27
Ma seule question est : est ce possible de faire ça dans une boucle générale?
Surement que oui ;-))
Peut être voir du côté d'une boucle "while true", avec des instructions "beak" et "continue" et le tout dans un "case ... esac" ;-\
Le tout sous réserve que ces commandes et instructions soient autorisées ;-)
Surement que oui ;-))
Peut être voir du côté d'une boucle "while true", avec des instructions "beak" et "continue" et le tout dans un "case ... esac" ;-\
Le tout sous réserve que ces commandes et instructions soient autorisées ;-)
zipe31
Messages postés
36402
Date d'inscription
dimanche 7 novembre 2010
Statut
Contributeur
Dernière intervention
27 janvier 2021
6 418
25 nov. 2010 à 23:17
25 nov. 2010 à 23:17
Bon je confirme c'est possible juste avec une boucle "while true" et des "breaks" ;-))
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre question
non je n'ai pas vu true ni breaks mais il me vient une autre idée: le script que tu as écrit, si on le modifie un peu pour le rendre récursif en rajoutant le cas de base "si il n'y a plus d'arguments on arrete l'exécution", que penses tu de cette idée? sans donner de code bien sur :-).
zipe31
Messages postés
36402
Date d'inscription
dimanche 7 novembre 2010
Statut
Contributeur
Dernière intervention
27 janvier 2021
6 418
26 nov. 2010 à 09:44
26 nov. 2010 à 09:44
Re-
en rajoutant le cas de base "si il n'y a plus d'arguments on arrete l'exécution"
Ben c'est ce que fait le script que j'ai testé, mais avec un "while true" et des "break" ;-((
Sans ces conditions je ne vois pas trop comment faire autrement ;-\
A suivre... ;-))
en rajoutant le cas de base "si il n'y a plus d'arguments on arrete l'exécution"
Ben c'est ce que fait le script que j'ai testé, mais avec un "while true" et des "break" ;-((
Sans ces conditions je ne vois pas trop comment faire autrement ;-\
A suivre... ;-))
Char Snipeur
Messages postés
9813
Date d'inscription
vendredi 23 avril 2004
Statut
Contributeur
Dernière intervention
3 octobre 2023
1 298
26 nov. 2010 à 10:12
26 nov. 2010 à 10:12
Salut.
Moi, je verrai bien une boucle en for in $@
ensuite, un case, si tu lis 'X', alors tu mets une variable à 1, si tu lis 'Y' tu met la variable à 2. Si tu lis autre chose, tu crée un répertoire si ta variable vaut 1 et n fichier si elle vaut 2.
Moi, je verrai bien une boucle en for in $@
ensuite, un case, si tu lis 'X', alors tu mets une variable à 1, si tu lis 'Y' tu met la variable à 2. Si tu lis autre chose, tu crée un répertoire si ta variable vaut 1 et n fichier si elle vaut 2.
zipe31
Messages postés
36402
Date d'inscription
dimanche 7 novembre 2010
Statut
Contributeur
Dernière intervention
27 janvier 2021
6 418
26 nov. 2010 à 10:34
26 nov. 2010 à 10:34
Salut,
Pas mieux et surtout très efficace ;-))
Pas mieux et surtout très efficace ;-))
salut, alors ok avec des case ça me va bien mais il n'est rien marqué dans mon cours dessus et j'ai cherché sur le net rien de convaincant non plus dessus, j'ai néanmoins testé un code ( qui ne marche pas , probleme de syntaxe ):
for i in "$@"
do
case $i in "-X"
$var=1;;
case $i in "Y"
$var=2;;
esac
if [ $i != "X" ] && [ $var = 1 ]
then
mkdir rep/$i
elif [ $i != "Y" ] && [ $var = 2 ]
then
touch rep/$i
fi
done
comment marche le case en fait, on fait case variable dans "valeur" ?
for i in "$@"
do
case $i in "-X"
$var=1;;
case $i in "Y"
$var=2;;
esac
if [ $i != "X" ] && [ $var = 1 ]
then
mkdir rep/$i
elif [ $i != "Y" ] && [ $var = 2 ]
then
touch rep/$i
fi
done
comment marche le case en fait, on fait case variable dans "valeur" ?
zipe31
Messages postés
36402
Date d'inscription
dimanche 7 novembre 2010
Statut
Contributeur
Dernière intervention
27 janvier 2021
6 418
26 nov. 2010 à 18:57
26 nov. 2010 à 18:57
Re-
Petit exemple :
;-))
Petit exemple :
$ cat case_marine.sh #! /bin/bash for i in "$@" do case "$i" in [0-9]) echo "$i est un chiffre." echo ;; [a-zA-Z]) echo "$i est une lettre." echo ;; *) echo "$i n'est ni un chiffre ni une lettre." echo ;; esac done $ ./case_marine.sh 1 a 2 3 A U N J , . p 5 $ F 1 est un chiffre. a est une lettre. 2 est un chiffre. 3 est un chiffre. A est une lettre. U est une lettre. N est une lettre. J est une lettre. , n'est ni un chiffre ni une lettre. . n'est ni un chiffre ni une lettre. p est une lettre. 5 est un chiffre. $ n'est ni un chiffre ni une lettre. F est une lettre. $
;-))
et bien j'avais bien compris le case alors pq mon code ne marche pas, j'ai ce message:
Erreur de syntaxe près du symbole inattendu « newline »
case $element in "X"'
Erreur de syntaxe près du symbole inattendu « newline »
case $element in "X"'
zipe31
Messages postés
36402
Date d'inscription
dimanche 7 novembre 2010
Statut
Contributeur
Dernière intervention
27 janvier 2021
6 418
26 nov. 2010 à 19:17
26 nov. 2010 à 19:17
Non ta syntaxe n'est pas bonne ;-((
Mauvais :
for i in "$@"
do
case $i in "-X"
$var=1;;
case $i in "Y"
$var=2;;
esac
Non :
Mauvais :
for i in "$@"
do
case $i in "-X"
$var=1;;
case $i in "Y"
$var=2;;
esac
Non :
for i in "$@" do case $i in X) var=1;; Y) var=2;; esac
d'accord, mais je deviens folle car dans cette expression vois tu une erreur zipe:
if [ "$i"!="-d" ] && [ $var -eq 1 ]
j'ai essayé tous les changements possibles et inimaginables dans var - eq... et c'est tjs une erreur de syntaxe, meme avec = , des guillements...
if [ "$i"!="-d" ] && [ $var -eq 1 ]
j'ai essayé tous les changements possibles et inimaginables dans var - eq... et c'est tjs une erreur de syntaxe, meme avec = , des guillements...
zipe31
Messages postés
36402
Date d'inscription
dimanche 7 novembre 2010
Statut
Contributeur
Dernière intervention
27 janvier 2021
6 418
Modifié par zipe31 le 26/11/2010 à 19:33
Modifié par zipe31 le 26/11/2010 à 19:33
Il me faut le script en entier, sans quoi pour moi "-d" et "$var" ne veulent rien dire ;-((
Au cas ou, comme ça (attention aux espaces) :
Au cas ou, comme ça (attention aux espaces) :
if [ "$i" != "-d" -a "$var" -eq 1 ]
voilà le script entier:
if [ $# -lt 1 ]
then
echo Il faut au moins un paramètre.
exit 1
fi
mkdir $1
shift [1]
var=""
for i in "$@"
do
case $i in
-d) $var=1;;
-f) $var=2;;
esac
if [ "$i" !="-d" ] && [ "$var" -eq 1 ]
then
mkdir rep/$i
elif [ "$i" !="-f" ] && [ "$var" -eq 2 ]
then
touch rep/$i
fi
done
if [ $# -lt 1 ]
then
echo Il faut au moins un paramètre.
exit 1
fi
mkdir $1
shift [1]
var=""
for i in "$@"
do
case $i in
-d) $var=1;;
-f) $var=2;;
esac
if [ "$i" !="-d" ] && [ "$var" -eq 1 ]
then
mkdir rep/$i
elif [ "$i" !="-f" ] && [ "$var" -eq 2 ]
then
touch rep/$i
fi
done
zipe31
Messages postés
36402
Date d'inscription
dimanche 7 novembre 2010
Statut
Contributeur
Dernière intervention
27 janvier 2021
6 418
26 nov. 2010 à 20:14
26 nov. 2010 à 20:14
Difficile de te répondre dans la mesure où il faudrait poster la solution pour te faire comprendre comment utiliser le "case" avec les "$var".
Ce que je peux te dire c'est que le test de '"$var"=1' doit se trouver dans le "case" dans la partie que tu as oublié le fameux "*)" (le reste en dehors des conditions "-d" et "-f") et le seul truc que tu auras à tester c'est le contenu de la variable "$var" ;-\
Ce que je peux te dire c'est que le test de '"$var"=1' doit se trouver dans le "case" dans la partie que tu as oublié le fameux "*)" (le reste en dehors des conditions "-d" et "-f") et le seul truc que tu auras à tester c'est le contenu de la variable "$var" ;-\
do case "$i" in -d) $var=1;; -f) $var=2;; *) if ... then ... else ... fi ;; esac
je ne comprends plus rien je sens que je vais abandonner, mon probleme c'est juste un probleme de syntaxe, impossible de le corriger? J'ai testé ton dernier message et rien n'y fait c'est tjs le meme probleme de syntaxe...
DOnc ok j'accepte la solution car ça fait 3 jours que je suis dessus et j'estime avoir assez cherché...
DOnc ok j'accepte la solution car ça fait 3 jours que je suis dessus et j'estime avoir assez cherché...
zipe31
Messages postés
36402
Date d'inscription
dimanche 7 novembre 2010
Statut
Contributeur
Dernière intervention
27 janvier 2021
6 418
26 nov. 2010 à 20:26
26 nov. 2010 à 20:26
$ cat foo.sh #! /bin/bash #set -xv if [ $# -lt 1 ] then echo Il faut au moins un paramètre. exit 1 fi echo "mkdir $1" shift for i in "$@" do case "$i" in X) VAR=1 ;; Y) VAR=2 ;; *) if [ "$VAR" = 1 ] then echo "mkdir $i" else echo "touch $i" fi ;; esac done $ ./foo.sh rep X a b c Y 1 2 3 X Q S D Y 7 8 9 mkdir rep mkdir a mkdir b mkdir c touch 1 touch 2 touch 3 mkdir Q mkdir S mkdir D touch 7 touch 8 touch 9
Char Snipeur
Messages postés
9813
Date d'inscription
vendredi 23 avril 2004
Statut
Contributeur
Dernière intervention
3 octobre 2023
1 298
27 nov. 2010 à 14:01
27 nov. 2010 à 14:01
manque le cas où l'utilisateur est con :
#!/bin/bash #set -xv if [ $# -lt 1 ] then echo Il faut au moins un paramètre. exit 1 fi VAR=0 echo "mkdir $1" shift for i in "$@" do case "$i" in X) VAR=1 ;; Y) VAR=2 ;; *) case $VAR in 1) echo "mkdir $i" ;; 2) echo "touch $i" ;; *) echo "mettre X ou Y avant toute chose"&&exit 1 ;; esac ;; esac donejuste à vérifier qu'on peu imbriquer deux case.
zipe31
Messages postés
36402
Date d'inscription
dimanche 7 novembre 2010
Statut
Contributeur
Dernière intervention
27 janvier 2021
6 418
27 nov. 2010 à 14:15
27 nov. 2010 à 14:15
Salut,
Tout d'abord merci pour l'algo, sans quoi j'étais parti dans des méandres digne des meilleurs labyrinthes ;-))
Si si des "case ... esac" peuvent parfaitement s'imbriquer.
Par contre on peut dans ce cas là insérer le cas oublié dans le "if" :
;-))
Tout d'abord merci pour l'algo, sans quoi j'étais parti dans des méandres digne des meilleurs labyrinthes ;-))
Si si des "case ... esac" peuvent parfaitement s'imbriquer.
Par contre on peut dans ce cas là insérer le cas oublié dans le "if" :
*) if [ "$VAR" = 1 ] then echo "mkdir $i" elif [ "$VAR" = 2 ] then echo "touch $i" else echo "mettre X ou Y avant toute chose" && exit 1 fi ;; esac
;-))
BIen, merci bcp pour ton aide ça marche, au moins j'aurais appris pleins de choses tant mieux, juste une question sur le case: le *) veut dire en fait: pour tous les autres valeurs différentes de X ou Y?
zipe31
Messages postés
36402
Date d'inscription
dimanche 7 novembre 2010
Statut
Contributeur
Dernière intervention
27 janvier 2021
6 418
26 nov. 2010 à 20:37
26 nov. 2010 à 20:37
le *) veut dire en fait: pour tous les autres valeurs différentes de X ou Y?
Oui.
Oui.