IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Shell et commandes GNU Discussion :

Double boucle while


Sujet :

Shell et commandes GNU

  1. #1
    Membre confirmé
    Homme Profil pro
    Analyse système
    Inscrit en
    Août 2020
    Messages
    160
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Analyse système
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2020
    Messages : 160
    Par défaut Double boucle while
    Bonjour,

    Sur 3 serveurs distincts, je souhaite faire un "ls -al" de 2 fichiers "file1" et "file2" que je mets dans un fichier FILE.txt :

    Fichier FILE.txt :
    De la même manière je fabrique un fichier SERVER.txt contenant les 3 serveurs en question et j'imagine une boucle while qui permet de lire ce fichier :

    Fichier SERVER.txt :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SERVER1
    SERVER2
    SERVER3
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    while read Serv; do
         echo $Serv
    done < SERVER.txt

    Je me sers donc de cette boucle while pour y insérer une seconde boucle permettant de lire FILE.txt pour chaque ligne de SERVER.txt.

    Le but est d'aller faire le "ls -al" pour les 2 fichiers sur les 3 serveurs et d'obtenir au final les 3 fichiers :

    FILE_SERVER1.txt :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    -rw-r--r-- 1 kevin kevin    21 Oct 13 12:02  file1
    -rw-r--r-- 1 kevin kevin    89 Oct 10 04:36  file2
    FILE_SERVER2.txt :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    -rw-r--r-- 1 kevin kevin    37 Oct 13 13:10  file1
    -rw-r--r-- 1 kevin kevin    45 Oct 10 09:01  file2
    FILE_SERVER3.txt :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    -rw-r--r-- 1 kevin kevin    11 Oct 09 14:09  file1
    -rw-r--r-- 1 kevin kevin    51 Oct 07 08:30  file2
    Pour cela :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    while read Serv; do
     
            while read File; do
                    ssh $Serv 'ls -al $File'
            done < FILE.txt >> FILE_"$Serv".txt
     
    done < SERVER.txt

    Sauf que je n'obtiens pas la totalité : uniquement 3 fichiers avec le "ls -al" de file1 mais pas du second file2, comme s'il n'y avait qu'un passage pour la seconde boucle.

    Quelque chose m'échappe…!

  2. #2
    Membre émérite Avatar de balkany
    Homme Profil pro
    Touriste
    Inscrit en
    Juillet 2017
    Messages
    348
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Touriste

    Informations forums :
    Inscription : Juillet 2017
    Messages : 348
    Par défaut
    ssh "$Serv" "ls -al $File" ?

  3. #3
    Membre confirmé
    Homme Profil pro
    Analyse système
    Inscrit en
    Août 2020
    Messages
    160
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Analyse système
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2020
    Messages : 160
    Par défaut
    Merci BALKANY pour ta réponse rapide,
    C'est juste un exemple (pas terrible j'en conviens) mais le souci c'est que la seconde boucle ne s'exécute qu'une fois.

  4. #4
    Membre émérite Avatar de balkany
    Homme Profil pro
    Touriste
    Inscrit en
    Juillet 2017
    Messages
    348
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Touriste

    Informations forums :
    Inscription : Juillet 2017
    Messages : 348
    Par défaut
    Je ne vois pas de raison à cela autre que le fait que FILE.txt n'ait qu'une seule ligne, mais en tout cas tu devrais mettre des guillemets doubles comme j'ai fait ci-dessus, car là, ta variable $File n'est pas prise en compte (à moins qu'elle ait une valeur sur la machine distante).

  5. #5
    Membre confirmé
    Homme Profil pro
    Analyse système
    Inscrit en
    Août 2020
    Messages
    160
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Analyse système
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2020
    Messages : 160
    Par défaut
    Merci.
    Le fichier FILE.txt a bien 2 lignes, mais la boucle ne fait qu'un passage pour je ne sais quelle raison.
    Il y a donc un souci dans ces 2 boucles imbriquées, la seconde n'est parcourue qu'une seule fois ! Il doit y avoir une subtilité...

  6. #6
    Expert confirmé Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 357
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4 357
    Par défaut
    Si tu as une liste de 50 fichiers, tu fais 50 connexions ssh sur le même serveur, tu ne trouve pas ça un peu bourrin ?

    D'ailleurs, ton souci est à chercher de ce coté là...

  7. #7
    Membre confirmé
    Homme Profil pro
    Analyse système
    Inscrit en
    Août 2020
    Messages
    160
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Analyse système
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2020
    Messages : 160
    Par défaut
    Merci.

    Il faudrait donc pour chaque serveur faire une seul connexion et passer les deux "ls -al" ?

    Pour un serveur, les résultats des 2 "ls -al" doivent être l'un à la suite de l'autre comme dans mon message initial.

    Donc pas de seconde boucle while ? Mais comment faire ?

    Ceci dit je me m'explique pas le fait que dans la seconde boucle il n'y a qu'un passage ?

  8. #8
    Expert confirmé Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 293
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 293
    Par défaut
    Bonjour

    • On n'utilise pas "ls" dans un script. "ls", c'est pour les humains. Les alternatives sont "find" et "stat".
    • Tes "while" imbriqués ne fonctionnent pas car ils se disputent l'entrée standard.
    • Une solution envisageable est l'utilisation de tableau. Mais, attention, ne jamais oublier les double quotes "". Si tes données ont des espaces, c'est la cata, sans double quotes.
      Une boucle for sur les tableaux n'aura plus de problème de flux.


    Code bash : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     
    # On prévient que tab est un tableau
    declare -a tab
    #On remplit le tableau
    while IFS='' read ligne
    do 
        tab+=("$ligne")
    done < file.txt
     
    # Cette boucle est un exemple, probablement équivalent à "cat".
    for i in "${tab[@]}"
    do 
        echo "$i"
    done
     
    # On vide le tableau
    unset tab

    Cet exemple ne fait pas d'imbrications. Mais tu sauras faire.


  9. #9
    Expert confirmé Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 357
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4 357
    Par défaut
    A la commande ls, tu peux lui passer une liste de fichier et pas uniquement un seul fichier à la fois.

    Après, si tu ne veux pas qu'il trie et qu'il donne dans l'ordre de ta liste, essaye avec l'option -f en premier, donc ls -fal "fichier1" "fichier2" "fichier3".

    Et suit le conseil de Flodelarab

  10. #10
    Membre confirmé
    Homme Profil pro
    Analyse système
    Inscrit en
    Août 2020
    Messages
    160
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Analyse système
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2020
    Messages : 160
    Par défaut
    Merci Flodelarab, c'est du high level je vais essayer déjà de comprendre avant de tenter l'imbrication, pas simple.
    Cependant, je dois me servir des 2 fichiers FILE.txt et SERVER.txt car il sont destinés à être modifiés sans toucher le code.

    Merci Disedorgue. Mais pour passer un nombre indéfini de commande que une seule ligne, à part la boucle.

    N'y a t-il pas un moyen de corriger ou modifier mon code initial pour que la seconde boucle soit lue entièrement et non une fois?

  11. #11
    Expert confirmé Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 293
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 293
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    while IFS='' read -r ligne
    do 
        tabfile+=("$ligne")
    done < file.txt
     
    while IFS='' read -r ligne
    do 
        tabserver+=("$ligne")
    done < server.txt
     
    for s in "${tabserver[@]}"
    do 
        for f in "${tabfile[@]}"
        do 
            echo "Commande sur le serveur $s avec le fichier $f"
        done
    done

  12. #12
    Expert confirmé Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 357
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4 357
    Par défaut
    Pour ne faire qu'une seule connexion par serveur, si je devais reprendre ton script initial, cela ferais un truc qui ressemblerait à ceci (pas testé) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    while read Serv; do
            ssh $Serv 'bash -s' < <(while read File; do echo ls -al \"$File\"; done < File.txt) >FILE_"$Serv".txt 
    done < SERVER.txt
    ATTENTION, ici le echo n'est pas facultatif.

  13. #13
    Membre confirmé
    Homme Profil pro
    Analyse système
    Inscrit en
    Août 2020
    Messages
    160
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Analyse système
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2020
    Messages : 160
    Par défaut
    Merci beaucoup pour vos réponses.

    Cependant, je m'en suis sorti avec une double boucle for toute simple…

  14. #14
    Membre confirmé
    Homme Profil pro
    Analyse système
    Inscrit en
    Août 2020
    Messages
    160
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Analyse système
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2020
    Messages : 160
    Par défaut
    Citation Envoyé par disedorgue Voir le message
    Pour ne faire qu'une seule connexion par serveur, si je devais reprendre ton script initial, cela ferais un truc qui ressemblerait à ceci (pas testé) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    while read Serv; do
            ssh $Serv 'bash -s' < <(while read File; do echo ls -al \"$File\"; done < File.txt) >FILE_"$Serv".txt 
    done < SERVER.txt
    ATTENTION, ici le echo n'est pas facultatif.
    Bonjour,

    Super, j'ai testé le "ls -al" et ca fonctionne.

    Par contre, à la place du "ls -al" on pourrait imaginer un "find" … et là il veut pas :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    do echo /bin/find \"$File\" -type f -printf '%s %p\n'
    /bin/find: paths must precede expression: %pn

    SOLUTION : mettre la commande entre guillemets

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    do echo "/bin/find \"$File\" -type f -printf '%s %p\n'"

    Comme je disais dans mon message précédent, avant de tester cette solution je m'en étais sorti avec une double boucle for et ça fonctionne même si c'est pas prévu pour faire ce genre de chose :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    for File in $(cat FILE.txt); do
        for Serv in $(cat SERVER.txt); do
           ssh $Serv 'ls -al "$File"' > FILE_"$Serv".txt
        done
    done

  15. #15
    Expert confirmé Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 357
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4 357
    Par défaut
    si, ça fonctionne si tu fais ce que dit le message d'erreur ...

    Je suppose que tu te connectes sur des AIX ou Solaris ?

    De manière générale, find prend un chemin depuis lequel il doit chercher le pattern qui peut être un nom de fichier:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    find chemin -name "pattern" ....
    Et pour faciliter les choses, il faut savoir que les find sont très différent selon les OS...

  16. #16
    Membre confirmé
    Homme Profil pro
    Analyse système
    Inscrit en
    Août 2020
    Messages
    160
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Analyse système
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2020
    Messages : 160
    Par défaut
    Depuis un Linux ...
    J’ai mis le find entre guillemets de ça marche !

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [MySQL] Double boucle while input select
    Par yurispy dans le forum PHP & Base de données
    Réponses: 17
    Dernier message: 15/12/2013, 23h06
  2. [MySQL] Optimisation code double boucle while
    Par heretik25 dans le forum PHP & Base de données
    Réponses: 3
    Dernier message: 18/11/2011, 15h38
  3. Quitter une double boucle while
    Par sirop-de-menthe dans le forum MATLAB
    Réponses: 3
    Dernier message: 13/05/2011, 23h05
  4. [PHP 5.3] Soucis avec le résultat d'une requête (double boucles while)
    Par beegees dans le forum Langage
    Réponses: 7
    Dernier message: 31/05/2010, 22h26
  5. [PHP 5.3] Double boucles while, problème d'accès au données de la première
    Par beegees dans le forum Langage
    Réponses: 3
    Dernier message: 09/11/2009, 08h44

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo