Partage
  • Partager sur Facebook
  • Partager sur Twitter

script bash débutant

Sujet résolu
    18 janvier 2021 à 19:59:49

    Bonsoir, 

    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

    Merci d'avance pour une quelconque réponse ! 

    -
    Edité par Cadogan 18 janvier 2021 à 20:01:01

    • Partager sur Facebook
    • Partager sur Twitter
      18 janvier 2021 à 21:04:05

      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.

      • Partager sur Facebook
      • Partager sur Twitter

      Validez la réponse utile « Un problème clairement exposé est à moitié résolu. » Pas de MP technique

        18 janvier 2021 à 21:36:34

        dantonq a écrit:

        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 ?

        -
        Edité par Cadogan 19 janvier 2021 à 0:59:06

        • Partager sur Facebook
        • Partager sur Twitter
          18 janvier 2021 à 23:48:30

          mets des guillemets autour des Remplacements de paramètres

          -
          Edité par dantonq 18 janvier 2021 à 23:48:57

          • Partager sur Facebook
          • Partager sur Twitter

          Validez la réponse utile « Un problème clairement exposé est à moitié résolu. » Pas de MP technique

            19 janvier 2021 à 1:05:12

            dantonq a écrit:

            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 ?


            • Partager sur Facebook
            • Partager sur Twitter
              19 janvier 2021 à 3:08:51

              > 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.
              • Partager sur Facebook
              • Partager sur Twitter
                19 janvier 2021 à 11:14:48

                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

                • Partager sur Facebook
                • Partager sur Twitter

                Validez la réponse utile « Un problème clairement exposé est à moitié résolu. » Pas de MP technique

                  19 janvier 2021 à 12:26:21

                  dantonq a écrit:

                  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 lance la cmd avec ./bash_summary.sh '*.txt' car d'après un exemple du cours sur ce langage je dois faire passer comme param *.txt et pas juste .txt (https://openclassrooms.com/fr/courses/43538-reprenez-le-controle-a-laide-de-linux/43464-les-boucles#/id/r-2284730)

                  Je suis vraiment bloqué, merci pour le temps que vous prenez pour me répondre


                  • Partager sur Facebook
                  • Partager sur Twitter
                    19 janvier 2021 à 14:14:21

                    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

                    • Partager sur Facebook
                    • Partager sur Twitter

                    Validez la réponse utile « Un problème clairement exposé est à moitié résolu. » Pas de MP technique

                      19 janvier 2021 à 19:09:02

                      dantonq a écrit:

                      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
                      • Partager sur Facebook
                      • Partager sur Twitter
                        19 janvier 2021 à 19:37:22

                        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

                        • Partager sur Facebook
                        • Partager sur Twitter

                        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.
                        • Editeur
                        • Markdown