xargs で引数が渡されると、最初の一致後に Zgrep が停止します。

xargs で引数が渡されると、最初の一致後に Zgrep が停止します。

このコマンドを使用して、zipファイルでパターンを見つけます(ここで提案されているパターンと似ています)。 https://superuser.com/questions/144926/unix-grep-for-a-string-within-all-gzip-files-in-all-subdirectories

find . -regex ".*/.*zip" | xargs zgrep -m 1 -E "PATTERN"

初戦以降もグレッピングは続いた。たぶんfind/xargs犯人かもしれません。grep最初の一致を見つけたら検索を停止するにはどうすればよいですか?

ポリスチレン最初の一致後にfindコマンドをどのように停止できますか?findfindの最初の一致だけでなく、成功した一致の後にgrepを停止する必要があるため、機能しません。

答え1

いくつか:

  • zgrep圧縮アーカイブ内のファイルで.zはなく圧縮ファイルを表示します。.gzzip

    zipgrepアーカイブを表示するために時々unzip一緒にバンドルされている(壊れた)スクリプトがありますが、このスクリプトzipの機能はegrepアーカイブのすべてのメンバーで実行されます(したがって、-m1各メンバーはegrep各ファイルの最初の発生を報告します)。

    zgrepgzip、各ファイルの出力を提供するスクリプトも同様です。ファイルを解凍できますが、アーカイブの最初のメンバーと圧縮されている場合にのみ可能です(ファイル内のすべてのメンバー、特に小さなメンバーを圧縮する必要はありません)。gzip -cdfqgrepgzip -dzipzip

  • xargs必要な数のコマンドを実行しますが、ファイルのリストが大きい場合は、複数のコマンドを実行できます。

ここで最良のオプションはzipgrep手動で実装することです(ここではGNUツールを使用して)。

find . -name '*.zip' -type f -exec sh -c '
    unzip -Z1 "$1" |
      while IFS= read -r file; do
        unzip -p "$1" "$file" | grep --label="$1//$file" -Hm1 -- "$0" && exit
      done' PATTERN {} \; -quit

各ファイルはシェルを実行しますが、より多くのコマンドもzipgrep実行します。zipgrep

アーカイブメンバーの名前にワイルドカード(*、、、[)などの文字(ASCII文字0x1〜0x1fなどのさまざまな文字)が含まれていると失敗することがありますが、これは?主にSo badのバグと制限によるものです。unzipzipgrep

答え2

努力する:

find . -iname '*.zip' -print0 | xargs -0r zgrep -l -E 'PATTERN'

-iname私は代わりに使用しました-regex。この方法もうまく機能し、私の考えでは、find奇妙な正規表現処理よりも混乱しません。スペースまたはシェルメタ文字を含むファイル名を正しく処理するには、-print0およびを使用します。xargs -0

grepオプションは-lマニュアルページに記載されています。

   -l, --files-with-matches
          Suppress  normal  output;  instead  print the name of each input
          file from which output would normally have  been  printed.   The
          scanning  will  stop  on  the  first match.

前述の最初の一致はファイルごとに行われるため、複数のファイルが一致するとすべて印刷されます。これは、一致するファイルが見つかった後でもgrepが他のファイルを検索し続けることを意味します。

最初の一致後に停止するには、greps--line-bufferedオプションを使用してgrepの出力をにパイプすることができますhead -1。最初の一致が印刷されるとhead印刷され、終了し、grep標準出力がなくなり、終了してfind従います。

find . -iname '*.zip' -print0 | xargs -0r zgrep --line-buffered -l -E 'PATTERN' | head -1

答え3

grep(またはzgrep-mオプションを使用すると読み取りが停止します。現在のファイル最初のゲームでは:

   -m NUM, --max-count=NUM
          Stop reading a file after NUM matching lines.  

検索はブロックされません。Next文書。たとえば、

$ echo "hello" > foo
$ echo "hello" > bar
$ grep -m 1 hello foo bar
foo:hello
bar:hello

したがって、問題はxargs複数のファイルを収集することではありません。最初の試合が終わった後に停止するためにgrep(または)zgrep文書、@Stephaneが提案したのと同じ小さなループを実行する必要があります。またはbashで同様のことをします。

shopt -s globstar
for i in **/*.zip; do
  zgrep -l pattern "$i" && break; 
done

またはzipアーカイブの場合複数のファイルが含まれています。(@Stephaneに感謝します):

shopt -s globstar
for i in **/*.zip; do
  if unzip -p "$i" | grep -q hello; then 
    echo "$i" && break;
  fi;
done

答え4

grep -m 1各ファイルの最初の項目をリストします。

パイプを介して最初の一致を一覧表示する簡単な方法がありますhead -n 1。まもなく検索になります信号パイプライン

find . -regex ".*/.*zip" -print0 | xargs -0 zgrep -E "PATTERN" | head -n 1

関連情報