2012-03-05 23:28:16 +0000 2012-03-05 23:28:16 +0000
148
148

Comment ignorer certains noms de fichiers en utilisant "find" ?

L'une de mes commandes BASH préférées est :

find . -name '*.*' -exec grep 'SearchString' {} /dev/null \;

qui recherche le contenu de tous les fichiers à l'intérieur et en dessous du répertoire courant pour la chaîne de recherche spécifiée. En tant que développeur, cela s'est avéré parfois utile.

En raison de mon projet actuel, et de la structure de ma base de code, j'aimerais cependant rendre cette commande BASH encore plus avancée en ne recherchant aucun fichier qui se trouve dans ou sous un répertoire contenant “.svn”, ou aucun fichier qui se termine par “.html”

La page MAN de recherche m'a cependant un peu embrouillé. J'ai essayé d'utiliser -prune, et cela m'a donné un comportement étrange. Pour essayer de ne sauter que les pages .html (pour commencer), j'ai essayé :

find . -wholename './*.html' -prune -exec grep 'SearchString' {} /dev/null \;

et n'ai pas obtenu le comportement que j'espérais. Je pense que je passe peut-être à côté de -prune. Pourriez-vous m'aider ?

Merci

Réponses (3)

209
209
209
2012-03-06 00:40:37 +0000

Vous pouvez utiliser la fonction de négation ( !) de la recherche pour ne pas faire correspondre les fichiers avec des noms spécifiques :

find . ! -name '*.html' ! -path '*.svn*' -exec grep 'SearchString' {} /dev/null \;

Donc si le nom se termine par .html ou contient .svn n'importe où dans le chemin, il ne correspondra pas, et donc l'exécutable ne sera pas exécuté.

12
12
12
2012-03-06 13:54:15 +0000

J'ai le même problème depuis longtemps, et il existe plusieurs solutions qui peuvent être applicables dans différentes situations :

  • ack-grep est une sorte de “grep” du développeur qui par défaut saute les répertoires de contrôle de version et les fichiers temporaires. La page man explique comment ne rechercher que des types de fichiers spécifiques et comment [ définir votre propre (https://github.com/l0b0/tilde/blob/master/.ackrc) ]. Les options
  • grep propre --exclude et --exclude-dir peuvent être utilisées très facilement pour sauter les répertoires de fichiers globs et single (pas de globbing pour les répertoires, malheureusement). Les options
  • find . \( -type d -name '.svn' -o -type f -name '*.html' \) -prune -o -print0 | xargs -0 grep ... devraient fonctionner, mais les options ci-dessus sont probablement moins problématiques à long terme.
9
9
9
2012-03-06 03:29:21 +0000

La commande find suivante permet d'élaguer les répertoires dont les noms contiennent .svn, Bien qu'elle ne descende pas dans le répertoire, le nom du chemin élagué est imprimé …(-name '*.svn' en est la cause !) ..

Vous pouvez filtrer les noms de répertoire via : grep -d skip qui ignore silencieusement les “noms de répertoires”.

Avec GNU grep, vous pouvez utiliser -H au lieu de /dev/null. Un léger problème secondaire : peut être beaucoup plus rapide que `\;`, par exemple pour 1 million de fichiers d'une ligne, en utilisant `\;` cela a pris _4m20s_, en utilisant cela a pris seulement 1.2s.

La méthode suivante utilise xargs au lieu de -exec, et suppose qu'il n'y a pas de nouvelles lignes \n dans aucun de vos noms de fichiers. Tel qu'utilisé ici, xargs est à peu près identique à “ de find.

xargs peut transmettre des noms de fichiers qui contiennent des espaces consécutifs en changeant le délimiteur d'entrée en '\n' avec l'option -d.

Cela exclut les répertoires dont le nom contient .svn et ne greffe que les fichiers qui ne se terminent pas par .html.

find . \( -name '*.svn*' -prune -o ! -name '*.html' \) |
   xargs -d '\n' grep -Hd skip 'SearchString'