Publicité
+ Répondre à la discussion
Affichage des résultats 1 à 13 sur 13
  1. #1
    Membre chevronné
    Avatar de hornetbzz
    Homme Profil pro
    Directeur commercial
    Inscrit en
    octobre 2009
    Messages
    482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France

    Informations professionnelles :
    Activité : Directeur commercial

    Informations forums :
    Inscription : octobre 2009
    Messages : 482
    Points : 741
    Points
    741

    Par défaut Trouver les fichiers contenant un texte CHAINE et afficher les lignes concernées

    En une ligne, on souhaite trouver dans quels fichiers se trouve la chaine CHAINE, lister leur chemin (relatif à notre position), et afficher les lignes contenant le fameux texte CHAINE.

    grep recursif :
    Code :
    grep -Rn "CHAINE" mon_repertoire/
    ou avec les couleurs, si votre grep et configuration le permettent :
    Code :
    grep --color -Rn "CHAINE" mon_repertoire/
    find + grep non récursif :
    Si on veut border la recherche avec des conditions plus strictes, par exemple, aux fichiers *.sh dont vous êtes l'utilisateur et qui sont executables :
    Code :
    find depuis_ce_repertoire/ -type f -user moi_hornetbzz -perm /u+x -name "*.sh" -exec grep --color -Hn "CHAINE" {} 2>/dev/null \;
    ------------------- on pourrait s'arrêter là pour la FAQ, sinon pour l'arrachage de cheveux ----------
    Pour l'exercice, une version Debian/Ubuntu si vous avez les couleurs dans votre terminal :
    La combinaison de 3 commandes de base find, grep et sed va nous permettre cela :

    Code :
    1
    2
    3
    4
    5
    6
    7
    DIR="mon_rep_de_recherche"; F_PATTERN="*"; CHAIN="ma_chaine_à_trouver"; COLOR=$'\033[1;33;40m'; \
    OFF=$'\E[0m'; find $DIR -type f -name "$F_PATTERN" -print0 | \
    while read -r -d "$(printf "\000")" -r path;\
    do [[ $(grep -r "$CHAIN" $path) ]] && ((count++)) && \
    echo -e "\nfile $count:  $path" && (grep -n "$CHAIN" $path | \
    sed -e "s/^\(.*\)/line \1/" -e 's/\('"$CHAIN"'\)/'"$COLOR"'\1'"$OFF"'/' ) ;\
    done
    Il y a très certainement une myriade d'autres solutions plus élégantes, en utilisant d'autres fonctions telles que awk/gawk ou bien en langage Perl. L'avantage de celle-ci réside dans l'utilisation de 3 commandes essentielles présentes dans toutes les distributions Linux, et dans la possibilité de sélectionner des fichiers particuliers (de type shell, et/ou avec les permissions executables et/ou appartenant à tel ou tel utilisateur etc...).

    [EDITED]
    Nota1: sed est utilisé dans son contexte "éditeur" et non "remplacement" de texte à proprement dit. Cette commande pourrait être omise.
    Nota2: la commande fonctionne en ligne de commande. Pour l'utiliser en Bourne Shell dans un script (#!/bin/sh) au lieu de Bash (#!/bin/bash) , il faudrait modifier ((count++)) par count=$((count+1)).
    Nota3: pour les développeurs qui utilisent Eclipse, cette commande est l'équivalent d'un search string. L'application évidente est la vérification ponctuelle de code sur un serveur en production.

  2. #2
    Expert Confirmé Sénior
    Profil pro
    Inscrit en
    janvier 2011
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : janvier 2011
    Messages : 1 717
    Points : 5 444
    Points
    5 444

    Par défaut

    Salut,

    Je trouve la solution un peu lourde et tortueuse, alors qu'un simple :

    Code :
    find $DIR -type f -name "*" -exec sed -i.bak 's/XXX/YYY/' {} 2>/dev/null \;
    devrait suffire à mon avis... excepté pour la portabilité de l'option "-i.bak"
    $ man woman
    Il n'y a pas de page de manuel pour woman.

  3. #3
    Expert Confirmé Sénior Avatar de frp31
    Homme Profil pro francois pussault
    Ingénieur systèmes et réseaux
    Inscrit en
    juillet 2006
    Messages
    4 739
    Détails du profil
    Informations personnelles :
    Nom : Homme francois pussault
    Âge : 38
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : juillet 2006
    Messages : 4 739
    Points : 11 291
    Points
    11 291

    Par défaut

    une solution non portable... c'est pas terrible...

  4. #4
    Membre Expert
    Homme Profil pro Alexis
    Responsable d'Exploitation
    Inscrit en
    février 2003
    Messages
    926
    Détails du profil
    Informations personnelles :
    Nom : Homme Alexis
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Responsable d'Exploitation
    Secteur : Biens de consommation

    Informations forums :
    Inscription : février 2003
    Messages : 926
    Points : 1 729
    Points
    1 729

    Par défaut

    [Mode avis personnel]
    Trop spécifique pour être vraiment pratique, et trop difficilement adaptable.
    L'exercice est intéressant sur le plan pratique, mais franchement, je n'utiliserais jamais ce genre de commande
    [/Mode avis personnel]

  5. #5
    Membre chevronné
    Avatar de hornetbzz
    Homme Profil pro
    Directeur commercial
    Inscrit en
    octobre 2009
    Messages
    482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France

    Informations professionnelles :
    Activité : Directeur commercial

    Informations forums :
    Inscription : octobre 2009
    Messages : 482
    Points : 741
    Points
    741

    Par défaut

    Citation Envoyé par zipe31 Voir le message
    Salut,

    Je trouve la solution un peu lourde et tortueuse, alors qu'un simple :

    Code :
    find $DIR -type f -name "*" -exec sed -i.bak 's/XXX/YYY/' {} 2>/dev/null \;
    devrait suffire à mon avis... excepté pour la portabilité de l'option "-i.bak"
    Attention: Remplacer "en aveugle" XX par YY n'est pas la vocation de la ligne de commande que je propose. Trop dangereux à mon sens et probablement pas adapté dans une FAQ où un copier/coller dans sa console peut vite conduire à la catastrophe.

    Ma proposition édite le path des fichiers et les lignes concernées par la recherche de texte. Volontairement sans risque. Essayes-la :-)
    A charge de l'utilisateur ensuite d'opérer un remplacement ou non selon son besoin. Alors il utilisera un sed de remplacement appliqué sur tel ou tel fichier. Ou une autre combinaison de commandes.

    Maintenant, il est certainement possible d'obtenir le même résultat autrement, je ne demande qu'à voir.

  6. #6
    Membre chevronné
    Avatar de hornetbzz
    Homme Profil pro
    Directeur commercial
    Inscrit en
    octobre 2009
    Messages
    482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France

    Informations professionnelles :
    Activité : Directeur commercial

    Informations forums :
    Inscription : octobre 2009
    Messages : 482
    Points : 741
    Points
    741

    Par défaut

    Citation Envoyé par Alek-C Voir le message
    [Mode avis personnel]
    Trop spécifique pour être vraiment pratique, et trop difficilement adaptable.
    L'exercice est intéressant sur le plan pratique, mais franchement, je n'utiliserais jamais ce genre de commande
    [/Mode avis personnel]
    Il n'y a rien à adapter.

  7. #7
    Expert Confirmé Sénior
    Profil pro
    Inscrit en
    janvier 2011
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : janvier 2011
    Messages : 1 717
    Points : 5 444
    Points
    5 444

    Par défaut

    Citation Envoyé par hornetbzz Voir le message
    Attention: Remplacer "en aveugle" XX par YY n'est pas la vocation de la ligne de commande que je propose. Trop dangereux à mon sens et probablement pas adapté dans une FAQ où un copier/coller dans sa console peut vite conduire à la catastrophe.

    Maintenant, il est certainement possible d'obtenir le même résultat autrement, je ne demande qu'à voir.
    Ok, alors quid de (mise à part l'absence de coloration) :

    Code :
    find $DIR -type f -name "*" -exec grep -Hn "${CHAIN}" {} 2>/dev/null \;
    $ man woman
    Il n'y a pas de page de manuel pour woman.

  8. #8
    Membre chevronné
    Avatar de hornetbzz
    Homme Profil pro
    Directeur commercial
    Inscrit en
    octobre 2009
    Messages
    482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France

    Informations professionnelles :
    Activité : Directeur commercial

    Informations forums :
    Inscription : octobre 2009
    Messages : 482
    Points : 741
    Points
    741

    Par défaut

    Oui ça fonctionne aussi mais cette commande est loin de réaliser toute la fonctionnalité.

  9. #9
    Membre Expert
    Homme Profil pro Alexis
    Responsable d'Exploitation
    Inscrit en
    février 2003
    Messages
    926
    Détails du profil
    Informations personnelles :
    Nom : Homme Alexis
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Responsable d'Exploitation
    Secteur : Biens de consommation

    Informations forums :
    Inscription : février 2003
    Messages : 926
    Points : 1 729
    Points
    1 729

    Par défaut

    Citation Envoyé par hornetbzz Voir le message
    Il n'y a rien à adapter.
    j'ai dit que c'était un avis personnel : si je ne veux pas "ligne :" mais "[ligne]", si je ne veux pas de couleur, si les couleurs ne passent pas sur mon terminal, si...

    en ce qui me concerne, ce n'est pas une commande que j'essaierais de retenir : elle est trop complexe et je n'en vois pas l'intérêt d'une manière générale

    De plus, j'ai fait un test pour voir ce que ça sortait comme résultat et ça n'a pas marché :
    Code :
    1
    2
    3
    $ DIR="."; F_PATTERN="*"; CHAIN="EZE"; COLOR=$'\033[1;33;40m'; OFF=$'\E[0m'; find $DIR -type f -name "$F_PATTERN" -print0 | while read -r -d "$(printf "\000")" -r path; do [[ $(grep -r "$CHAIN" $path) ]] && ((count++)) && echo -e "\nfile $count:  $path" && (grep -n "$CHAIN" $path | sed -e "s/^\(.*\)/line \1/" -e 's/\('"$CHAIN"'\)/'"$COLOR"'\1'"$OFF"'/' ) ; done
    $ grep -Rn EZE *
    t2/test.txt:3:dfgdfgd EZE elmfkdjlmfk
    La première commande ne renvoie rien, pourtant, je pense avoir correctement configuré les 3 variables (le find seul fonctionne en tout cas) ?

    Pour le fun, j'ai mis les couleurs que grep retourne tout seul comme un grand sur mon serveur (gentoo).

    Sur une machine Unix (HP-UX) sous ksh, la commande plante également :
    Code :
    1
    2
    $ DIR="."; F_PATTERN="*"; CHAIN="EZE"; COLOR=$'\033[1;33;40m'; OFF=$'\E[0m'; find $DIR -type f -name "$F_PATTERN" -print0 | while read -r -d "$(printf "\000")" -r path; do [[ $(grep -r "$CHAIN" $path) ]] && ((count++)) && echo -e "\nfile $count:  $path" && (grep -n "$CHAIN" $path | sed -e "s/^\(.*\)/line \1/" -e 's/\('"$CHAIN"'\)/'"$COLOR"'\1'"$OFF"'/' ) ; done
    ksh: syntax error: `]]' unexpected
    En bref, sur un linux récent, j'ai grep qui fait ce que je crois avoir compris que ta commande faisait, et sur une machine plus ancienne, je pense qu'elle ne marchera pas !

    Mais encore une fois, c'est un avis personnel, et cela n'empêche pas que je trouve la commande très intéressante sur un plan pédagogique : je vais essayer de retenir la méthode utilisée (couplage de print0, de read, ...) qui pourra me servir un jour, mais pas au point d'en faire une commande générique !

  10. #10
    Membre chevronné
    Avatar de hornetbzz
    Homme Profil pro
    Directeur commercial
    Inscrit en
    octobre 2009
    Messages
    482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France

    Informations professionnelles :
    Activité : Directeur commercial

    Informations forums :
    Inscription : octobre 2009
    Messages : 482
    Points : 741
    Points
    741

    Par défaut

    ok pour le grep -Rn, 100% d'accord, c'est clairement plus portable pour quasiment le même résultat. Je modifie en conséquence.

  11. #11
    Expert Confirmé Sénior
    Profil pro
    Inscrit en
    janvier 2011
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : janvier 2011
    Messages : 1 717
    Points : 5 444
    Points
    5 444

    Par défaut

    Citation Envoyé par hornetbzz Voir le message
    Oui ça fonctionne aussi mais cette commande est loin de réaliser toute la fonctionnalité.
    C'est vrai il manque le compteur

    Pour la couleur, rajouter "--color" à grep (pour les versions qui l'accepte) :

    Code :
    find $DIR -type f -name "*" -exec grep --color -Hn "${CHAIN}" {} 2>/dev/null \;
    $ man woman
    Il n'y a pas de page de manuel pour woman.

  12. #12
    Membre chevronné
    Avatar de hornetbzz
    Homme Profil pro
    Directeur commercial
    Inscrit en
    octobre 2009
    Messages
    482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France

    Informations professionnelles :
    Activité : Directeur commercial

    Informations forums :
    Inscription : octobre 2009
    Messages : 482
    Points : 741
    Points
    741

    Par défaut



    Merci.

    J'ai édité la proposition initiale (c'est vrai, un tantinet "tortueuse" mais c'était zoli comme (une) Eclipse ) pour tenir compte de vos remarques et distinguer les deux cas d'utilisation de grep (recursif en soi ou recursivité obtenue par la combinaison avec find).

  13. #13
    Responsable Modération

    Avatar de ok.Idriss
    Homme Profil pro Idriss Neumann
    Consultant en SSII et ingénieur CNAM Paris (spécialité SI)
    Inscrit en
    février 2009
    Messages
    5 047
    Détails du profil
    Informations personnelles :
    Nom : Homme Idriss Neumann
    Âge : 24
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Consultant en SSII et ingénieur CNAM Paris (spécialité SI)
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : février 2009
    Messages : 5 047
    Points : 17 476
    Points
    17 476

    Par défaut

    Bonjour.

    Une nouvelle Q/R a été rajoutée à la FAQ sur la base de la proposition d'hornetbzz : Comment trouver les fichiers contenant une chaîne de caractères et afficher les lignes concernées ?



    Idriss
    mes cours sur DVP | initiation aux bases de données relationnelles | FAQ Linux | FAQ tests
    la programmation Shell | bonnes pratiques Bash | exercices shells scripts & Bash corrigés
    Merci aussi de lire les règles du club

    "Forgiveness does not change the past, but it does enlarge the future." (Paul Boese)
    Traduction approximative : le pardon ne change pas le passé mais élargit l'horizon de l'avenir.

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

Liens sociaux

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •