Forum Linux.débutant Script bash

Posté par  . Licence CC By‑SA.
0
2
nov.
2018

Bonjour,

j'essaye de faire un script qui permet de à un utilisateur de saisir le chemin du répertoire qui l'intéresse et d'ensuite le diriger vers ce dernier.

après plusieurs tentative je ne comprends pas pourquoi mon script ne marche pas :
1)

#!ban/bash

read -p 'veuillez indiquez un chemin ' chemin
cd < echo $chemin

exec $SHELL

2)

 #!ban/bash

read -p 'quel répértoire vous intéresse aujourdhui?veuillez indiquez un chemin ' chemin
cd < $chemin

exec $SHELL

3)

#!ban/bash

read -p 'quel répértoire vous intéresse aujourdhui?veuillez indiquez un chemin ' chemin
cd $chemin

exec $SHELL

je vous remercie d'avance pour votre aide,

  • # use the force luke

    Posté par  . Évalué à 2.

    hmm, tu connais la commande cd

    c'est par defaut sur tous les shells

    l'utilisateur tape :
    cd lechemin/vers/ou/il/veut/aller

    et hop, magie ca l'envoie dans le dossier qu'il a demandé

    • [^] # Re: use the force luke

      Posté par  . Évalué à 1.

      Merci, et oui je connais déjà cette commande sinon je l'aurais pas mis sur mon script haha.

      cependant je souhaiterai l'utiliser dans un script avec saisie de l'utilisateur

  • # 1ère ligne

    Posté par  (site web personnel) . Évalué à 2.

    c'est normal ce shebang?

    • [^] # Re: 1ère ligne

      Posté par  . Évalué à 1. Dernière modification le 02 novembre 2018 à 14:52.

      non c'était une erreur de ma part, merci !

  • # Des pistes ?

    Posté par  (site web personnel) . Évalué à 3.

    • pourquoi ban/bash ?
    • attention avec l'apostrophe d'aujourd'hui et celles du read
    • pourquoi exec ?
    • [^] # Re: Des pistes ?

      Posté par  . Évalué à 1.

      une erreur pour le ban/bash ! merci
      sans exec mon programme execute pas la commande cd. (j'ai essayé avec cd ~/Téléchargements/ et sans exec shell ça ne marche pas, vu que j'essaye avec une saisie utilisateur j'ai gardé l'exec)

  • # Sous-shell

    Posté par  (site web personnel) . Évalué à 3.

    Quand tu lances ton script (avec /bin/bash et non ban/bash), il lance un autre process dans lequel exécuter les commandes. Ta commande cd va donc s'éxéctuer (et tu peux tester en ajoutant un ls pour voir les fichiers dans le répertoire courant). Par contre, une fois ton script terminé, tu reviens sur ton environnement d'origine (qui est aussi un environnement bash) mais dans lequel aucune commande n'a été exécutée.

    Si tu veux modifier l'environnement d'exécution il ne faut pas lancer ton script via exec, mais par source ou . test.sh

    • [^] # Re: Sous-shell

      Posté par  . Évalué à 4. Dernière modification le 02 novembre 2018 à 11:21.

      Salut,

      ou . test.sh

      Ce n'est pas gentil d'introduire une potentielle source d'erreur aux nouveaux :)

      Ici, mis à part le nom absolument pas parlant du script, pas (trop) de soucis. On aurait peut-être pu privilégier cependant un nom plus parlant, comme custom_cd.sh (ou autre, hein !).

      Là où le bas blesse avec ces codes sources nommées test.*, c'est un exemple vécu :

      • l'élève crée un code test.c,
      • l'élève le compile, ce qui donne sans erreur un exécutable test,
      • l'élève l'exécute, et il ne se passe « rien ».

      Eh oui, test étant une fonction bash également, c'est elle qui prend la main lors d'un simple appel à test (sans chemin relatif !), alors que tout semble bon, même la complétion dans le shell.

      Moralité : mieux vaut préférer un nom parlant, même pour un « test ».

      Matricule 23415

    • [^] # Re: Sous-shell

      Posté par  . Évalué à 3.

      Par contre, une fois ton script terminé, tu reviens sur ton environnement d'origine (qui est aussi un environnement bash) mais dans lequel aucune commande n'a été exécutée.

      exec remplace le shell courant (celui du script, pas celui d’origine) par la commande qu’on lui passe en paramètre (ici, la valeur de $SHELL).

      Donc normalement, en remplaçant #!ban/bash par #!/bin/bash (avec un i et un / en plus au début), la version 3 devrait fonctionner avec deux bémols :

      • le shell sera celui du script et pas celui d’origine ($SHELL indique le shell actuel, donc ici, celui d’exécution du script — ou alors il faut réécrire le script dans un langage qui ne soit pas un shell pour que la variable SHELL ne soit pas affectée) ;
      • quand on sortira du shell, on retombera sur le shell d’origine.

      Je ne vois pas de manière d’éviter ces inconvénients, à part, plutôt que de créer un script, de définir une fonction dans le .bashrc (pour bash) :

      chemin () {
          read -p "Entrez un nouveau chemin : " chemin
          cd $chemin
      }

      ATTENTION : des erreurs dans le .bashrc pourraient causer des soucis ! Mieux vaut mettre au point dans un autre fichier en utilisant la commande source pour tester et ne recopier dans le .bashrc qu’ensuite.

      « Le fascisme c’est la gangrène, à Santiago comme à Paris. » — Renaud, Hexagone

    • [^] # Re: Sous-shell

      Posté par  . Évalué à 1.

      en fait le script une fois exécuté me sort une erreur : ligne 4: echo: Aucun fichier ou dossier de ce type, alors que je tape le chemin correctement !!

      c'est dire qu'il faut que je remplace exec avec source, ou . test.sh ? quelle est la différence?

      • [^] # Re: Sous-shell

        Posté par  . Évalué à 4. Dernière modification le 02 novembre 2018 à 17:55.

        Dans la commande

        cd < echo $chemin

        < echo remplace l’entrée standard par le contenu d’un fichier nommé echo du répertoire courant.

        Le message d’erreur indique logiquement qu’il n’y en a pas.

        La bonne commande est

        cd "$chemin"

        en tenant compte de la remarque tout-à-fait pertinente de wismerhill (on ne pense jamais assez à quoter).

        « Le fascisme c’est la gangrène, à Santiago comme à Paris. » — Renaud, Hexagone

  • # Dans le même esprit

    Posté par  (site web personnel) . Évalué à 3. Dernière modification le 03 novembre 2018 à 20:30.

    Une version améliorée avec de quoi manger pour tout comprendre lorsqu'on débute ;-)

    #!/bin/bash
    read -p 'veuillez indiquez un chemin ' chemin
    [ -d "${chemin}" ] || { echo "path ${chemin} not exists" 1>&2; exit 1; }
    cd "${chemin}"
    
    [ -x "${SHELL}" ] || { echo "shell ${SHELL} not executable" 1>&2; exit 2; }
    grep -q "${SHELL}" /etc/shells || { echo "${SHELL} not a valid shell" 1>&2; exit 3; }
    exec ${SHELL}

    J'ai mis quelques barrières de protection ici ou là ainsi qu'une petite gestion d'erreur. À noter qu'on lance comme dans l'original un sous shell ce qui est un choix possible selon ce que l'on souhaite…

    • [^] # Re: Dans le même esprit

      Posté par  . Évalué à 1.

      Merci !

      mais honnêtement je comprends pas trop ton code et il m'indique une erreur :
      path ~/Téléchargements/ not exists

      • [^] # Re: Dans le même esprit

        Posté par  (site web personnel) . Évalué à 2. Dernière modification le 03 novembre 2018 à 20:31.

        Normal, ~ est un joker interne du bash pour dire $HOME… Il doit donc être évalué par le bash. Après la ligne read, mettre un eval

             read -p 'veuillez indiquez un chemin ' chemin
             chemin=$(eval echo ${chemin})

        Le eval évalue la chaîne et s'il y a un tilde, remplace par la valeur de $HOME… Cependant, je ne sais pas en terme de sécurité ce que cela donne, pas top top bien qu'on évalue juste un echo !

        Pour le reste, je ne vais pas te donner toutes les billes mais ce n'est pas très compliqué, chaque ligne est indépendante et se lit en elle même. "man bash" pour comprendre certaines choses ;-)

        • [^] # Re: Dans le même esprit

          Posté par  (site web personnel) . Évalué à 2.

          D'ailleurs, en y réfléchissant, il vaudrait mieux éviter de pouvoir faire passer l'option -e à echo. Une solution que je vois est de rajouter une chaîne mais echo ne prends pas la chaîne spéciale '--' marquant la fin des options ! Il faut donc la supprimer après coup.

          chemin=$(eval echo -- "${chemin}" | sed -e 's/^-- //;')

          • [^] # Re: Dans le même esprit

            Posté par  . Évalué à 3.

            Ou mieux: utiliser printf, qui est plus puissante, dont le comportement est, il me semble, moins dépendant du shell utilisé, et surtout, on sait que seul ce qui est dans la chaîne de formatage sera affiché, il n'y a pas besoin de se demander si l'option "--truc" est connue ou non.

            Sinon, si l'anglais n'est pas une barrière, il y a ce bon vieux grymoire.com/ qui peut aider à comprendre ton script initial (et aussi, pour marquer les blocs de code, utilises le ```bash en 1ère ligne précédée d'une ligne vide pour commencer et le ``` seul sur une ligne après la fin, le résultat est plus lisible).

            • [^] # Re: Dans le même esprit

              Posté par  (site web personnel) . Évalué à 2.

              Pas idiot le triple ` ! Commande système pour printf, ne sais pas les effets de bord possible, à voir car c'est aussi effectivement intéressant ;-)

              #!/bin/bash
              
              read -p 'veuillez indiquez un chemin ' chemin
              
              # in order to accept ~ for ${HOME} - echo could be replace by printf
              chemin=$(eval echo -- "${chemin}" | sed -e 's/^-- //;')
              
              # verify path is a directory
              [ -d "${chemin}" ] || { echo "path ${chemin} not exists" 1>&2; exit 1; }
              
              cd "${chemin}"
              
              # verify ${SHELL} binary : executable and define in the system list
              [ -x "${SHELL}" ] || { echo "shell ${SHELL} not executable" 1>&2; exit 2; }
              grep -q "${SHELL}" /etc/shells || { echo "${SHELL} not a valid shell" 1>&2; exit 3; }
              
              exec ${SHELL}
              • [^] # Re: Dans le même esprit

                Posté par  (site web personnel) . Évalué à 2.

                Gare au eval, y a moyen de faire des trucs … pas drole (genre /tmp/$(rm -rf /)/hello …)

                • [^] # Re: Dans le même esprit

                  Posté par  (site web personnel) . Évalué à 4.

                  C'est vrai. Cela dit, tu fait un bête cd avec le même paramètre que tu as le même résultat ;-)

                  Pour cela que je ne faisais pas d'eval en première version et que je n'en fait quasiment jamais dans mes scripts ;-)

              • [^] # Re: Dans le même esprit

                Posté par  . Évalué à 2.

                Pas idiot le triple `

                Bah, ça me permets de faire moins d'efforts pour comprendre, et tant mieux si ça aide les autres.

                Commande système pour printf, ne sais pas les effets de bord possible

                C'est simple: les mêmes que pour echo, le flou en moins, la flexibilité en plus. Globalement, printf semble être plus recommandé, bien que je n'aie pas de source à citer.
                Ce qui est certain, c'est que juste le 1er paramètre détermine ce que tu afficheras réellement, et que les options de format sont nettement plus riches. Reste à savoir le poids du binaire en RAM et en ROM, qui peut impacter des usages embarqués. Mais dans l'embarqué, il est ridicule d'utiliser GNU, mieux vaut partir sur un *BSD ou busybox, le code est nettement plus concis, souvent en sacrifiant les locales, mais, c'est l'embarqué…

                En tout cas, l'important, c'est que tu sois content :)

  • # Chez moi ça marche

    Posté par  (Mastodon) . Évalué à 2. Dernière modification le 02 novembre 2018 à 15:25.

    Pour moi le 3) est la bonne solution (*), d'ailleurs il marche très bien chez moi. C'est quoi ton soucis exactement ?

    (*) bon, il y a moyen de faire plus léger, mais admettons que ce soit le but de l'exercice

    En théorie, la théorie et la pratique c'est pareil. En pratique c'est pas vrai.

    • [^] # Re: Chez moi ça marche

      Posté par  . Évalué à 5.

      Le problème du 3, c'est que $chemin n'est pas protégé par des guillemets, donc s'il y a dedans des espaces (ou d'autres choses amusantes), le cd ne fonctionnera pas (voir t'amènera dans un autre répertoire, s'il y en a un qui correspond au nom résultant).

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.