Précédent   Forum du club des développeurs et IT Pro > Systèmes > Linux > Contribuez
Contribuez Vos contributions pour la rubrique Linux : articles, cours, tutoriels, faq, comparatifs, tests, sources, ...
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse
 
Outils de la discussion
Publicité
'
Vieux 01/03/2011, 06h50   #1
hornetbzz
Membre chevronné
 
Avatar de hornetbzz
 
Homme
Directeur commercial
Inscription : octobre 2009
Messages : 481
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 45
Localisation : France

Informations professionnelles :
Activité : Directeur commercial

Informations forums :
Inscription : octobre 2009
Messages : 481
Points : 719
Points : 719
Envoyer un message via Skype™ à hornetbzz
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.
hornetbzz est déconnecté   Envoyer un message privé Réponse avec citation 30
Vieux 01/03/2011, 09h50   #2
zipe31
Expert Confirmé Sénior
 
Inscription : janvier 2011
Messages : 1 481
Détails du profil
Informations personnelles :
Localisation : France, Haute Garonne (Midi Pyrénées)

Informations forums :
Inscription : janvier 2011
Messages : 1 481
Points : 4 501
Points : 4 501
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.
zipe31 est déconnecté   Envoyer un message privé Réponse avec citation 20
Vieux 01/03/2011, 11h26   #3
frp31
Expert Confirmé Sénior
 
Avatar de frp31
 
Homme francois
Ingénieur systèmes et réseaux
Inscription : juillet 2006
Messages : 4 244
Détails du profil
Informations personnelles :
Nom : Homme francois
Âge : 36
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 244
Points : 10 484
Points : 10 484
une solution non portable... c'est pas terrible...
frp31 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/03/2011, 13h52   #4
Alek-C
Membre Expert
 
Homme Alexis
Responsable d'Exploitation
Inscription : février 2003
Messages : 925
Détails du profil
Informations personnelles :
Nom : Homme Alexis
Âge : 34
Localisation : France

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

Informations forums :
Inscription : février 2003
Messages : 925
Points : 1 766
Points : 1 766
Envoyer un message via ICQ à Alek-C Envoyer un message via Skype™ à Alek-C
[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]
Alek-C est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 01/03/2011, 15h02   #5
hornetbzz
Membre chevronné
 
Avatar de hornetbzz
 
Homme
Directeur commercial
Inscription : octobre 2009
Messages : 481
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 45
Localisation : France

Informations professionnelles :
Activité : Directeur commercial

Informations forums :
Inscription : octobre 2009
Messages : 481
Points : 719
Points : 719
Envoyer un message via Skype™ à hornetbzz
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.
hornetbzz est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 01/03/2011, 15h26   #6
hornetbzz
Membre chevronné
 
Avatar de hornetbzz
 
Homme
Directeur commercial
Inscription : octobre 2009
Messages : 481
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 45
Localisation : France

Informations professionnelles :
Activité : Directeur commercial

Informations forums :
Inscription : octobre 2009
Messages : 481
Points : 719
Points : 719
Envoyer un message via Skype™ à hornetbzz
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.
hornetbzz est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 01/03/2011, 15h30   #7
zipe31
Expert Confirmé Sénior
 
Inscription : janvier 2011
Messages : 1 481
Détails du profil
Informations personnelles :
Localisation : France, Haute Garonne (Midi Pyrénées)

Informations forums :
Inscription : janvier 2011
Messages : 1 481
Points : 4 501
Points : 4 501
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.
zipe31 est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 01/03/2011, 15h33   #8
hornetbzz
Membre chevronné
 
Avatar de hornetbzz
 
Homme
Directeur commercial
Inscription : octobre 2009
Messages : 481
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 45
Localisation : France

Informations professionnelles :
Activité : Directeur commercial

Informations forums :
Inscription : octobre 2009
Messages : 481
Points : 719
Points : 719
Envoyer un message via Skype™ à hornetbzz
Oui ça fonctionne aussi mais cette commande est loin de réaliser toute la fonctionnalité.
hornetbzz est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 01/03/2011, 15h46   #9
Alek-C
Membre Expert
 
Homme Alexis
Responsable d'Exploitation
Inscription : février 2003
Messages : 925
Détails du profil
Informations personnelles :
Nom : Homme Alexis
Âge : 34
Localisation : France

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

Informations forums :
Inscription : février 2003
Messages : 925
Points : 1 766
Points : 1 766
Envoyer un message via ICQ à Alek-C Envoyer un message via Skype™ à Alek-C
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 !
Alek-C est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 01/03/2011, 16h05   #10
hornetbzz
Membre chevronné
 
Avatar de hornetbzz
 
Homme
Directeur commercial
Inscription : octobre 2009
Messages : 481
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 45
Localisation : France

Informations professionnelles :
Activité : Directeur commercial

Informations forums :
Inscription : octobre 2009
Messages : 481
Points : 719
Points : 719
Envoyer un message via Skype™ à hornetbzz
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.
hornetbzz est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/03/2011, 16h09   #11
zipe31
Expert Confirmé Sénior
 
Inscription : janvier 2011
Messages : 1 481
Détails du profil
Informations personnelles :
Localisation : France, Haute Garonne (Midi Pyrénées)

Informations forums :
Inscription : janvier 2011
Messages : 1 481
Points : 4 501
Points : 4 501
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.
zipe31 est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 01/03/2011, 17h01   #12
hornetbzz
Membre chevronné
 
Avatar de hornetbzz
 
Homme
Directeur commercial
Inscription : octobre 2009
Messages : 481
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 45
Localisation : France

Informations professionnelles :
Activité : Directeur commercial

Informations forums :
Inscription : octobre 2009
Messages : 481
Points : 719
Points : 719
Envoyer un message via Skype™ à hornetbzz


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).
hornetbzz est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse
Outils de la discussion

Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 23h25.


 
 
 
 
Partenaires

Hébergement Web