185 votes

Comment ignorer certains noms de fichiers à l'aide de "find" ?

Une de mes commandes BASH préférées est :

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

qui recherche la chaîne de recherche spécifiée dans le contenu de tous les fichiers situés dans le répertoire actuel et en dessous. En tant que développeur, cela m'a parfois été utile.

Cependant, en raison de mon projet actuel et de la structure de ma base de code, j'aimerais rendre cette commande BASH encore plus avancée en ne recherchant pas les fichiers qui se trouvent dans ou sous un répertoire contenant ".svn", ou les fichiers qui se terminent par ".html".

La page MAN de find m'a 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 je n'ai pas obtenu le comportement que j'espérais. Je pense que je n'ai pas compris l'intérêt de -prune. Pourriez-vous m'aider ?

Gracias

262voto

Oliver Points 125

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

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

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

13voto

Nick T Points 38411

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

  • ack-grep est une sorte de "guide du développeur". grep " qui par défaut ignore les répertoires de contrôle de version et les fichiers temporaires. Le site man La page explique comment rechercher uniquement des types de fichiers spécifiques et comment définir votre propre .
  • grep de l'entreprise --exclude y --exclude-dir peuvent être utilisées très facilement pour sauter un fichier gants y simple (pas de globbing pour les répertoires, malheureusement).
  • find . \( -type d -name '.svn' -o -type f -name '*.html' \) -prune -o -print0 | xargs -0 grep ... devrait fonctionner, mais les options ci-dessus sont probablement moins contraignantes à long terme.

11voto

Peter.O Points 2933

Les éléments suivants find La commande élague les répertoires dont les noms contiennent .svn Bien qu'il 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 entrées de type "noms de répertoire".

Avec GNU grep, vous pouvez utiliser -H au lieu de /dev/null . Un petit problème secondaire : \+ peut être beaucoup plus rapide que \; par exemple, pour 1 million de fichiers d'une ligne, en utilisant \; il a fallu 4m20s en utilisant \+ il a fallu 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 l'un de vos fichiers noms . Tel qu'utilisé ici, xargs est à peu près la même que celle de find \+ .

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

Cela exclut les répertoires dont le nom contiennent .svn et recherche seulement les fichiers qui ne se terminent pas par .html .

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

2voto

George Smith Points 181

Cet exemple exclut de la recherche les fichiers dont le nom contient le mot "test". La recherche elle-même cherche "ProductReplacement" pour les fichiers XML uniquement.

find . ! -name '*test*.*' -name '*.xml' -exec grep -i 'ProductReplacement' {} \; -print

Vous pouvez spécifier plus de patetrns d'exclusion avec des patrons supplémentaires

! -nom 'file_pattern' (modèle de fichier) entrées.

2voto

En utilisant " -non " et " -et " :

find . -type f \( \
    -not -name "${1}" \
    -and -not -name "${2}" \
\)

En une ligne :

find . -type f \( -not -name "${1}" -and -not -name "${2} \)

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