J'ai un répertoire avec ~ 1 million de fichiers et j'ai besoin de rechercher des modèles particuliers. Je sais comment faire pour tous les fichiers :
find /path/ -exec grep -H -m 1 'pattern' {} ;
La sortie complète n'est pas souhaitée (trop lente). Plusieurs premiers hits sont corrects, j'ai donc essayé de limiter le nombre de lignes :
find /path/ -exec grep -H -m 1 'pattern' {} ; | head -n 5
Cela donne 5 lignes suivies de
find: `grep' terminated by signal 13
et find
continue de travailler. C'est bien expliqué ici. J'ai essayé de quit
action :
find /path/ -exec grep -H -m 1 'pattern' {} ; -quit
Cela ne génère que la première correspondance.
Est-il possible de limiter la sortie de recherche avec un nombre spécifique de résultats (comme fournir un argument pour quit
similaire à head -n
) ?
Réponse acceptée :
Puisque vous utilisez déjà les extensions GNU (-quit
, -H
, -m1
), vous pourriez aussi bien utiliser GNU grep
's -r
option, avec --line-buffered
il affiche donc les correspondances dès qu'elles sont trouvées, il est donc plus probable qu'un SIGPIPE soit tué dès qu'il écrit la 6ème ligne :
grep -rHm1 --line-buffered pattern /path | head -n 5
Avec find
, vous devrez probablement faire quelque chose comme :
find /path -type f -exec sh -c '
grep -Hm1 --line-buffered pattern "[email protected]"
[ "$(kill -l "$?")" = PIPE ] && kill -s PIPE "$PPID"
' sh {} + | head -n 5
C'est-à-dire envelopper grep
en sh
(vous voulez toujours exécuter aussi peu de grep
autant d'invocations que possible, d'où le {} +
), et ont sh
tuer son parent (find
) quand grep
meurt d'un SIGPIPE.
Une autre approche pourrait être d'utiliser xargs
comme alternative à -exec {} +
. xargs
quitte immédiatement lorsqu'une commande qu'il génère meurt d'un signal donc dans :
find . -type f -print0 |
xargs -r0 grep -Hm1 --line-buffered pattern |
head -n 5
(-r
et -0
étant des extensions GNU). Dès que grep
écrit dans le tube cassé, à la fois grep
et xargs
va sortir et find
se quittera également la prochaine fois qu'il imprimera quelque chose après cela. Exécution de find
sous stdbuf -oL
pourrait le faire arriver plus tôt.
Une version POSIX pourrait être :
trap - PIPE # restore default SIGPIPE handler in case it was disabled
RE=pattern find /path -type f -exec sh -c '
for file do
awk '''
$0 ~ ENVIRON["RE"] {
print FILENAME ": " $0
exit
}''' < "$file"
if [ "$(kill -l "$?")" = PIPE ]; then
kill -s PIPE "$PPID"
exit
fi
done' sh {} + | head -n 5
Très inefficace car il exécute plusieurs commandes pour chaque fichier.
En relation:Ubuntu - Comment verrouiller la vitesse du ventilateur pour AMD GPU dans Ubuntu 20.04 ?