Je veux sortir toutes les lignes contenant le mot OK
récursivement à partir d'un directory. Mais il y a quelques extensions que je dois exclure du résultat:
*~ *.map *.js except *.debug.js
J'ai essayé:
grep -r --exclude={*~,*.map} "OK" /some/dir
Sauf que je ne sais pas comment supprimer du résultat tous ces files .js
non-debug. Toute aide est très appréciée.
Je voudrais juste passer cela à travers un deuxième grep
pour les supprimer:
grep -r --exclude={\*~,\*.map} "OK" bar/ | grep -vP '(?<!debug)\.js'
Le -v
inverse la correspondance, imprimant des lignes qui ne correspondent pas au motif et le -P
active les expressions régulières compatibles avec Perl, ce qui nous permet d'utiliser des lookbehinds négatifs . Cette regex particulière correspondra à .js
qui n'est pas précisée par debug
ce qui signifie (puisque nous inversons les correspondances) que seuls les files .js
seront imprimés.
Cependant, comme @QuestionOverflow l'a souligné dans les commentaires, cela pourrait avoir l'effet secondaire involontaire de filterr les lignes qui contiennent OK
et js
puisque le grep -v
est appliqué à toute la sortie, pas seulement le nom du file. Pour éviter cela, il suffit d'append un deux-points (c'est ce que grep
utilise pour séparer les noms de files du contenu du file):
grep -r --exclude={*~,*.map} "OK" bar/ | grep -vP '(?<!debug).js:'
Cela échouera toujours si votre ligne d'input contient foo.js:
ou si votre nom de file contient foo.js:
Donc, pour être sûr, utiliser une approche différente:
grep -Tr --exclude={*~,*.map} "OK" bar/ | grep -vP '(?<!debug).js\t'
Le -T
provoque grep
à imprimer un onglet entre le nom du file et le contenu du file. Donc, si nous ajoutons simplement un \t
à la fin de l'expression rationnelle, il ne fera que correspondre aux noms de files, et non au contenu de la ligne.
Pourtant, l' utilisation de find
peut avoir plus de sens indépendamment.
Je voudrais utiliser find
pour localiser les files et canaliser le résultat via xargs
:
$ find . -type f \! -name "*~" \ \! -name "*.map" \ \! \( -name "*.js" -and \! -name "*.debug.js" \) \ -print0 | xargs -0 grep "OK"
Cela search tous les files ne correspondant pas " *~
", " *.map
" ou " *.js
mais pas *.debug.js
".
En utilisant find
vous pouvez facilement searchr des règles assez complexes et cette approche vous évite de supprimer accidentellement des faux positifs, ce qui pourrait arriver avec grep
double.
Avec zsh
vous pouvez faire:
setopt extendedglob grep OK some/dir/**/^(*~|*.map|(^*debug).js)
Bien entendu, la list d'arguments n'est pas trop longue, auquel cas vous pouvez toujours faire:
printf '%s\0' some/dir/**/^(*~|*.map|(^*debug).js) | xargs -0 grep OK
Si cela ne vous dérange pas de voir la sortie légèrement en panne (si vous le faites, vous pouvez le sortinger):
grep -r --exclude={*~,*.map,*.js} "OK" /some/dir **/*.debug.js
Cela nécessite que votre shell shopt -s globstar
charge **
pour les globes récursifs: zsh sort de la boîte, bash fait après avoir exécuté shopt -s globstar
, ksh93 fait après avoir exécuté set -o globstar
.
Sans support **
dans le shell, vous pouvez utiliser deux commands grep:
grep -r --exclude={*~,*.map,*.js} "OK" /some/dir grep -r --include=*.debug.js "OK" /some/dir