rechercher et faire écho les noms de fichiers uniquement avec un motif trouvé


Réponses:


24
find . -name '*.py' -exec grep something {} \; -print

afficherait le nom du fichier après les lignes correspondantes.

find . -name '*.py' -exec grep something /dev/null {} +

afficherait le nom du fichier devant chaque ligne correspondante (nous ajoutons /dev/nullpour le cas où il n'y a qu'un seul fichier correspondant car grepn'imprime pas le nom du fichier s'il est passé qu'un seul fichier à regarder. L'implémentation GNU de grepa une -Hoption pour cela comme alternative).

find . -name '*.py' -exec grep -l something {} +

afficherait uniquement les noms de fichier des fichiers qui ont au moins une ligne correspondante.

Pour imprimer le nom du fichier avant les lignes correspondantes, vous pouvez utiliser awk à la place:

find . -name '*.py' -exec awk '
  FNR == 1 {filename_printed = 0}
  /something/ {
    if (!filename_printed) {
      print FILENAME
      filename_printed = 1
    }
    print
  }' {} +

Ou appelez grepdeux fois pour chaque fichier - mais ce serait moins efficace car il exécuterait au moins une grepcommande et jusqu'à deux pour chaque fichier (et lirait le contenu du fichier deux fois):

find . -name '*.py' -exec grep -l something {} \; \
                    -exec grep something {} \;

Dans tous les cas, vous ne voulez pas faire une boucle sur la sortie de ce findgenre et n'oubliez pas de citer vos variables .

Si vous vouliez utiliser une boucle shell, avec les outils GNU:

find . -name '*.py' -exec grep -l --null something {} + |
   xargs -r0 sh -c '
     for file do
       printf "%s\n" "$file"
       grep something < "$file"
     done' sh

(fonctionne également sur FreeBSD et ses dérivés).


6

Si vous utilisez GNU grep, vous pouvez utiliser son option -rou --recursivepour effectuer cette recherche simple pour vous:

grep -r --include '*.py' -le "$regexp" ./ # for filenames only
grep -r --include '*.py' -He "$regexp" ./ # for filenames on each match

Vous n'avez besoin que findsi vous avez besoin de prédicats plus avancés.


1
Selon la version de GNU grep, greppeut ou non regarder à l'intérieur des liens symboliques ou traverser des liens symboliques vers des répertoires. Vous pouvez également trouver des variations dans la gestion d'autres types de fichiers non réguliers.
Stéphane Chazelas

5

Vous pouvez dire à grep d'inclure le nom de fichier dans la sortie. Donc, s'il y a une correspondance, elle sera affichée sur la console; s'il n'y a pas de correspondance dans un fichier, aucune ligne ne sera imprimée pour ce fichier.

find . -name "*.py" | xargs grep -n -H something

Du man grep:

-H       Always print filename headers with output lines
-n, --line-number
         Each output line is preceded by its relative line number in the file, starting at line 1.  The line number counter is reset for each file processed.
         This option is ignored if -c, -L, -l, or -q is specified.

Si vos fichiers peuvent avoir des noms avec des espaces, vous devez changer le canal pour utiliser des caractères NUL comme séparateur. La commande complète ressemblera maintenant à ceci:

find . -name "*.py" -print0 | xargs -0 grep -n -H something

1

Vous pouvez essayer quelque chose comme:

find . -name "*.py:" -exec grep -l {} \;

Cette commande exec grep pour chaque fichier, découverte par la commande find et sa fonction de commande find standard


1

Utilisez l' -largument.

for file in `find . -name "*.py"`; do grep -l something $file && grep something $file; done

Une utilisation plus trouvaille serait:

for file in $(find . -name '*.py' -exec grep -l something '{}' +); do echo "$file"; grep something $file; done

1

Il existe des grepalternatives qui, par défaut, affichent leurs résultats dans le format souhaité. Les 2 plus populaires que je connais sont ag(aka "le chercheur d'argent") et ack. agest annoncé comme une alternative plus rapide à ack.

$ ag '^\w+\s*\w+\(' ~/build/i3/src
build/i3/src/display_version.c
58:void display_running_version(void) {

build/i3/src/load_layout.c
42:static TAILQ_HEAD(focus_mappings_head, focus_mapping) focus_mappings =
518:json_content_t json_determine_content(const char *filename) {
575:void tree_append_json(Con *con, const char *filename, char **errormsg) {

build/i3/src/x.c
64:CIRCLEQ_HEAD(state_head, con_state) state_head =
67:CIRCLEQ_HEAD(old_state_head, con_state) old_state_head =
70:TAILQ_HEAD(initial_mapping_head, con_state) initial_mapping_head =
97:void x_con_init(Con *con, uint16_t depth) {
...

Je ne peux pas vous montrer ici, mais la sortie est bien colorée. Je reçois les noms de fichiers en vert olive, les numéros de ligne en jaune doré et la pièce assortie de chaque ligne en rouge sang. Les couleurs sont cependant personnalisables.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.