GNU/Linux >> Znalost Linux >  >> Linux

Omezit najít výstup a vyhnout se signálu 13?

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?
Linux
  1. Výstup do Stdout a zároveň Grep do souboru?

  2. Přesměrování a výstup potrubí?

  3. Jste zmateni Grepem a zástupným znakem *?

  1. Pomocí grep vyhledejte obsah v souborech a přesuňte je, pokud se shodují

  2. Použití grep a sed k nalezení a nahrazení řetězce

  3. Hledání spustitelných souborů pomocí ls a grep

  1. Najděte a přejmenujte adresář

  2. Ubuntu grep, find atd.:Oprávnění odepřeno a žádný takový výstup souboru nebo adresáře

  3. Jak grep ps výstup s hlavičkami