Mám adresář s ~ 1M soubory a potřebuji hledat konkrétní vzory. Vím, jak to udělat pro všechny soubory:
find /path/ -exec grep -H -m 1 'pattern' {} ;
Plný výkon není žádoucí (příliš pomalý). Několik prvních zásahů je v pořádku, tak jsem se pokusil omezit počet řádků:
find /path/ -exec grep -H -m 1 'pattern' {} ; | head -n 5
Výsledkem je 5 řádků následovaných
find: `grep' terminated by signal 13
a find pokračuje v práci. Tady je to dobře vysvětleno. Zkusil jsem quit akce:
find /path/ -exec grep -H -m 1 'pattern' {} ; -quit
Výsledkem je pouze první shoda.
Je možné omezit výstup hledání na konkrétní počet výsledků (jako je poskytnutí argumentu pro quit podobně jako head -n )?
Přijatá odpověď:
Protože již používáte rozšíření GNU (-quit , -H , -m1 ), můžete také použít GNU grep ‘s -r spolu s --line-buffered takže vypíše shody, jakmile jsou nalezeny, takže je pravděpodobnější, že bude zabit SIGPIPE, jakmile napíše 6. řádek:
grep -rHm1 --line-buffered pattern /path | head -n 5
Pomocí find , pravděpodobně budete muset udělat něco jako:
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
To znamená, že zabalte grep v sh (stále chcete spustit jako málo grep vyvolání, proto {} + ) a mají sh zabít jeho rodiče (find ), když grep zemře na SIGPIPE.
Dalším přístupem může být použití xargs jako alternativu k -exec {} + . xargs okamžitě opustí, když příkaz, který spustí, zemře na signál, takže v:
find . -type f -print0 |
xargs -r0 grep -Hm1 --line-buffered pattern |
head -n 5
(-r a -0 jako GNU rozšíření). Jakmile grep zapíše do přerušené roury, obě grep a xargs ukončí se a find sám se také ukončí, až bude příště něco tisknout. Spuštění find pod stdbuf -oL může se to stát dříve.
Verze POSIX by mohla být:
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
Velmi neefektivní, protože pro každý soubor spouští několik příkazů.
Související:Ubuntu – Jak uzamknout rychlost ventilátoru pro amd gpu v Ubuntu 20.04?