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?