54 votes

Comment utiliser grep sur tous les fichiers de manière non récursive dans un répertoire ?

Je veux rechercher une chaîne de texte dans tous les fichiers d'un répertoire (et non pas dans ses sous-répertoires ; je sais que l'option -r le fait, mais ce n'est pas ce que je veux).

  1. Running

    grep "string" /path/to/dir

    est censé pouvoir faire cela, j'ai lu, mais il me donne l'erreur :

    grep : dir : est un répertoire

  2. Ensuite, j'ai essayé de lancer grep sur plusieurs fichiers.

    grep "string" .bashrc .bash_aliases fonctionne parfaitement.

    grep "string" .bash* fonctionne également comme prévu.

    grep "string" * me donne les erreurs :

    grep: data: Is a directory
    grep: Desktop: Is a directory
    grep: Documents: Is a directory
    grep: Downloads: Is a directory
    ...

Seules les erreurs sont imprimées, je n'obtiens pas les lignes correspondantes. J'ai essayé d'utiliser la fonction -s mais en vain.

Donc, mes questions :

  1. Pourquoi ne suis-je pas en mesure d'utiliser grep sur un répertoire, comme dans (1), alors que je devrais pouvoir le faire ? J'ai vu cela dans de nombreux exemples sur Internet.
    Modifier : Quand je dis "utiliser grep sur un répertoire", je veux dire "rechercher dans tous les fichiers de ce répertoire en excluant ses sous-répertoires". Je crois que c'est ce que fait grep lorsque vous lui passez un répertoire à la place d'un fichier. Est-ce que je me trompe ?

  2. S'il vous plaît, donnez-moi une explication sur le fonctionnement de grep qui expliquerait le comportement des commandes dans (2).
    Modifier : Permettez-moi d'être plus précis. Pourquoi l'utilisation de caractères génériques pour spécifier plusieurs fichiers dans lesquels effectuer une recherche fonctionne-t-elle avec .bash* et non avec * ou même ./* ?

  3. Comment puis-je rechercher tous les fichiers d'un répertoire (et non pas ses sous-répertoires) en utilisant la commande grep ?

56voto

wjandrea Points 13147

En Bash, un glob ne se développe pas dans les fichiers cachés, donc si vous voulez rechercher todos les fichiers d'un répertoire, vous devez spécifier les fichiers cachés. .* et non caché * .

Pour éviter les erreurs "Is a directory", vous pourriez utiliser -d skip mais sur mon système, j'obtiens également une erreur grep: .gvfs: Permission denied † Je suggère donc d'utiliser -s qui masque tous les messages d'erreur.

Donc la commande que vous cherchez est :

grep -s "string" * .*

Si vous recherchez des fichiers dans un autre répertoire :

grep -s "string" /path/to/dir/{*,.*}

Une autre option consiste à utiliser le dotglob L'option Shell, qui fera en sorte qu'un glob inclut des fichiers cachés.

shopt -s dotglob
grep -s "string" *

Pour les fichiers dans un autre répertoire :

grep -s "string" /path/to/dir/*

† Quelqu'un a mentionné que je ne devrais pas avoir cette erreur. Ils ont peut-être raison - j'ai fait quelques lectures mais je n'ai pas réussi à m'y retrouver moi-même.

12voto

anonymous2 Points 4119

Vous avez besoin de la -d skip option ajoutée.

  1. Grep recherche à l'intérieur des fichiers. Vous pouvez effectuer une recherche récursive, comme vous l'avez dit, si vous souhaitez rechercher des fichiers à l'intérieur d'un répertoire.

  2. Par défaut, grep lira tous les fichiers, et il détecte les répertoires. Parce que par défaut, vous n'avez pas défini ce qu'il faut faire avec les répertoires avec la directive -d l'option, il donne une sortie d'erreur.

  3. Une recherche dans le seul répertoire parent serait grep -d skip "string" ./*

8voto

dathompson Points 81

Les anciens feraient probablement ça :

find . -type f -print0 | xargs -0 grep "string"

2voto

Criggie Points 489

Reformulation - vous voulez grep les fichiers dans un niveau de sous-répertoire, mais ne pas récurer à travers tous les sous-sous-répertoires ?

grep forthis  *  */*

Ou si vous ne voulez pas que les fichiers soient dans le répertoire courant

grep forthis  */*

Notez que cela ne trouvera pas les répertoires commençant par un point.

grep forthis  .*/*    */*   

devrait faire ce travail.

Il y a aussi -maxdepth y -mindepth paramètres de restriction disponibles pour le find également.

2voto

Dragos Alexe Points 121

Vous pouvez penser comme ceci, par exemple en utilisant grep.

grep -l PATH ~/.[^.]*

Donc cette recherche de la chaîne "PATH" listant le nom des fichiers sous le répertoire personnel de l'utilisateur, uniquement pour les fichiers qui commencent par un point .

/root/.bash_history
/root/.bash_profile
grep: /root/.cache: Is a directory
grep: /root/.config: Is a directory
grep: /root/.dbus: Is a directory

En utilisant grep PATH ~/.[^.]*, vous verrez toutes les occurrences, y compris la ligne contenant le mot clé recherché.

/root/.bash_history:echo $PATH
/root/.bash_history:echo $PATH
/root/.bash_history:PATH=$PATH:~/bin
/root/.bash_history:echo $PATH
/root/.bash_profile:PATH=$PATH:$HOME/bin
/root/.bash_profile:export PATH
grep: /root/.cache: Is a directory
grep: /root/.config: Is a directory
grep: /root/.dbus: Is a directory

Pour se débarrasser de l'erreur rediriger vers /dev/null par exemple

grep PATH ~/.[^.]* 2>/dev/null

/root/.bash_history:echo $PATH
/root/.bash_history:echo $PATH
/root/.bash_history:PATH=$PATH:~/bin
/root/.bash_history:echo $PATH
/root/.bash_profile:PATH=$PATH:$HOME/bin
/root/.bash_profile:export PATH

Vous pouvez donc appliquer ce modèle pour rechercher la chaîne "Apache" dans les fichiers du répertoire /etc en ne regardant que les fichiers situés sous ce répertoire principal. Vous voyez que cela ne revient pas dans /etc/httpd/conf/httpd.conf

grep Apache /etc/[^.]* 2>/dev/null
/etc/passwd:apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin
/etc/services:derby-repli     4851/tcp                # Apache Derby Replication
/etc/services:derby-repli     4851/udp                # Apache Derby Replication

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X