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 :

Effectuer une tache sur chaque itération de diff --recursive


Sujet :

Shell et commandes GNU

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé Avatar de nanooby
    Homme Profil pro
    IT Consultant
    Inscrit en
    Mai 2014
    Messages
    103
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : IT Consultant
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Mai 2014
    Messages : 103
    Par défaut Effectuer une tache sur chaque itération de diff --recursive
    Bonjour à tous !

    Comme vous pouvez le remarquer, je suis nouveau, et surtout je suis un novice en programmation de scripts en Shell.
    Je travaille actuellement sur un projet pour mon stage de fin d'études, et je me retrouve aujourd’hui un peu ennuyé/bloqué.

    Je doit m'occuper de l'automatisation des tests sur une solution en place depuis maintenant plus de 25ans (oui en 25ans ils n'ont pas mis en place de tests...).
    Là, je me penche sur la comparaison des résultats, insérés dans des fichiers XML, à des résultats stockés dans un autre dossier qui servent de modèle (résultats récupérés lors du lancement des tests avec une solution fonctionnelle).
    J'utilise donc la commande diff sur les dossiers où sont stockés les résultats et les modèles :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    diff --recursive DossierResultat DossierModele >> Erreurs.txt
    La commande diff me retourne la liste des erreurs, lorsqu'il y en a.
    Le problème est que j'ai besoin que sur chaque itération de diff (chaque comparaison qu'il fait), je récupère le résultat et le nom des fichiers pour afficher dans un autre fichier txt :

    • test1 : OK
    • test2 : KO
    • ...
    Sachant que test1 correspond au nom du premier fichier de résultat, test2 au nom du deuxième fichier de résultat...

    Bref là je n'arrive pas du tout à mettre la main sur la solution, google est pratique mais dans mon cas il ne m'aide pas beaucoup. C'est pourquoi je fais maintenant appel à vous

  2. #2
    Expert confirmé Avatar de BufferBob
    Profil pro
    responsable R&D vidage de truites
    Inscrit en
    Novembre 2010
    Messages
    3 041
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : responsable R&D vidage de truites

    Informations forums :
    Inscription : Novembre 2010
    Messages : 3 041
    Par défaut
    salut,

    je vois au moins deux façons de faire, la première en partant de l'output de diff et en le parsant à coup de awk ou de perl par exemple, du genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    LANG=fr_FR.UTF-8 diff -rdsN rep1/ rep2/ | awk '
    /^Les fichiers.+ sont identiques$/ {
       gsub(/^.+\//,"",$(NF-2));
       print $(NF-2) " : OK";
       next;
    }
    /^diff -rdsN / {
       gsub(/^.+\//,"",$4);
       print $4 " : KO";
    }'
    (note que j'ai déroulé le script awk pour plus de lisibilité mais le tout tient en une ligne)

    la deuxième en faisant un script à l'ancienne et en se basant plutôt sur find pour lister les fichiers et le code de retour de diff pour déterminer si les fichiers sont différents, quelque chose du style :
    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
    #!/bin/bash
     
    liste=$(find rep1/ -type f -exec basename {} \; | sort)
     
    for fichier in $liste; do
            if [ ! -e "rep2/${fichier}" ]; then  # est-ce que le fichier existe ?
                    echo "$fichier : KO"
            else
                    diff -urdsN rep1/${fichier} rep2/${fichier} >/dev/null 2>&1
                    ret=$?
                    if [ $ret -ne 0 ]; then  # si fichiers identiques, diff renvoit 0, sinon autre chose (à minima renvoit 1)
                            echo "${fichier} : KO"
                    else
                            echo "${fichier} : OK"
                    fi
            fi
    done
    c'est probablement pas ultime mais ça fonctionne, convient d'adapter au besoin

  3. #3
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 651
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 651
    Par défaut
    je ne dis rien
    je ne l'ai pas vu
    je ne dis rien
    je ne l'ai pas vu ...
    ...
    je ne peux pas : je l'ai vu, je ne peux pas ne rien dire



    je milite pour qu'on itère pas sur la sortie d'une commande avec une boucle for, car elle tourne sur chaque mot, et non sur chaque ligne.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    n=""; find ./ -maxdepth 1 -type f -name "fichier*" -print0 | while read -d '' f; do echo "$((++n)) - $f"; done
    1 - ./fichier avec des espaces
    2 - ./fichier avec
    un alinea
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  4. #4
    Expert confirmé Avatar de BufferBob
    Profil pro
    responsable R&D vidage de truites
    Inscrit en
    Novembre 2010
    Messages
    3 041
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : responsable R&D vidage de truites

    Informations forums :
    Inscription : Novembre 2010
    Messages : 3 041
    Par défaut
    oops

    pour ma défense j'ai précisé que c'était pas ultime et fait à la va-vite comme script, mais tu as raison en plus le for en bash est excessivement lent

  5. #5
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 832
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 832
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par N_BaH Voir le message
    je milite...
    Moi, j'aurais plutôt dit "je vous implore à genoux en toutes les larmes de mon corps"...

    ok
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  6. #6
    Membre confirmé Avatar de nanooby
    Homme Profil pro
    IT Consultant
    Inscrit en
    Mai 2014
    Messages
    103
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : IT Consultant
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Mai 2014
    Messages : 103
    Par défaut
    Tout d'abord, merci d'avoir pris le temps de me répondre

    @BufferBob : Concernant la "bonne vieille méthode", j'espérais ne pas avoir à m'en servir dans ce cas là, donc si je peux faire sans, je préfère. Par contre, je dois me servir de cette même méthode pour le lancement des tests (le diff me sert pour la comparaison des résultats, mais je comptai me pencher sur le lancement dynamique après), donc ce n'est pas perdu !!! En prenant en compte la correction de N_Bah évidemment

    Maintenant je voudrais rester sur cette première façon de faire. Je suis un peu (beaucoup) débutant, et j'essaie de la comprendre, mais difficilement. Donc awk j'avais déjà vu un peu. Tu utilises gsub pour retirer les caractères spéciaux, par contre $(NF-2), moi pas comprendre ce que ça être...

    Note : j'ai cherché, je sais à quoi correspond NF maintenant, mais j'ai toujours pas pas compris pourquoi tu l'utilises là.
    Même chose derrière, pourquoi $4? Là je m'y perd un peu. C'est évident pour vous mais si vous pouviez m'éclairer un peu

    2ème interrogation : comment sait-il que les fichiers sont identiques? J'ai lu que diff renvoi une valeur (0 si OK, 1 si KO, autre si erreur). Est-ce grâce à cette valeur?

    Encore merci pour vos réponses et ces quelques rires de bon matin

  7. #7
    Expert confirmé Avatar de BufferBob
    Profil pro
    responsable R&D vidage de truites
    Inscrit en
    Novembre 2010
    Messages
    3 041
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : responsable R&D vidage de truites

    Informations forums :
    Inscription : Novembre 2010
    Messages : 3 041
    Par défaut
    salut,

    Citation Envoyé par nanooby Voir le message
    Tout d'abord, merci d'avoir pris le temps de me répondre
    (...) awk j'avais déjà vu un peu. Tu utilises gsub pour retirer les caractères spéciaux, par contre $(NF-2), moi pas comprendre ce que ça être... (...) Même chose derrière, pourquoi $4?
    gsub remplace tout depuis le début de la chaine jusqu'au dernier / par une chaine vide, donc ça permet de ne conserver que ce qui suit à savoir le nom du fichier à proprement parler
    NF est une variable awk prédéfénie qui pour chaque ligne renvoit le nombre de "champs" qu'elle contient, et dans le même ordre d'idée $4 fait référence au 4ème champs, chaque champs étant séparé des autres par un ou plusieurs espaces et/ou tabulations par défaut
    en clair $(NF-2) fait référence à l'avant-avant-dernier mot de la ligne et $4 au 4ème mot de la ligne

    dans le code awk on cherche à matcher 2 types de lignes dans l'output de diff grâce aux regex /^Les fichiers.+ sont identiques$/ et /^diff -rdsN /;

    - les lignes du genre "Les fichiers repertoire1/fichier350 et repertoire2/fichier350 sont identiques" pour lesquelles l'avant-avant-dernier "mot" vaut repertoire2/fichier350, qu'on passe ensuite à gsub etc.

    - les lignes du genre "diff -rdsN repertoire1/fichier809 repertoire2/fichier809" qui sont caractéristiques de différences entre les fichiers (en général on une ligne de ce genre et en dessous les différences au format unifié diff), et pour laquelle $4 vaudra repertoire2/fichier809.

    cette méthode qui utilise des paramètres positionnels ($(NF-2) et $4) ne fonctionne correctement que si l'output de diff est formaté comme on l'a prévu, c'est la raison pour laquelle j'ai rajouté explicitement un LANG=fr_FR.UTF-8 devant le diff, pour m'assurer que quelque soit l'environnement (cron par exemple) la commande me renverra bien un output en français que awk sera capable de parser

    comment sait-il que les fichiers sont identiques? J'ai lu que diff renvoi une valeur (0 si OK, 1 si KO, autre si erreur). Est-ce grâce à cette valeur?
    c'est ça, la variable bash $? contient le code de retour de la dernière commande exécutée

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

Discussions similaires

  1. Script qui effectue une commande sur chaque dossier de son listing
    Par nc13160 dans le forum Windows Serveur
    Réponses: 0
    Dernier message: 24/07/2012, 16h21
  2. Effectuer une tache sur plusieures Feuilles
    Par LaPanic dans le forum Macros et VBA Excel
    Réponses: 10
    Dernier message: 07/07/2008, 11h14
  3. [VBA]Exécuter une tache sur chaque ligne d'une table
    Par Tierisa dans le forum VBA Access
    Réponses: 1
    Dernier message: 13/04/2007, 16h53
  4. effectuer une opération sur chaque ligne d'un select
    Par Mindiell dans le forum MS SQL Server
    Réponses: 4
    Dernier message: 20/12/2006, 12h23
  5. Réponses: 1
    Dernier message: 28/03/2005, 12h33

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