私のEメールバックアップで重要なEメールを検索しようとしています。何千ものファイルを含むサブディレクトリを含むディレクトリ.eml
(Linuxファイルシステムの場合)。.eml
3つの単語を含むテキストファイルを検索し、1つの単語を除外したいと思います。
まず、ある単語を検索してから、パイプを介して別の単語を検索してみます。
grep -R 'foo' ~/Directory/path | grep 'bar'
これは、同じ行に2つの単語を含むファイルのみを返すため、機能しません。ファイル全体に2つの単語を含むファイルが必要です。
私は単語を含むファイルを見つけて、ファイルの内容を出力ファイルにリンクしようとしています。
grep -rIlZ '.' -e 'foo' | xargs -0 cat > MyOutputFile
文脈を見ることができるので役に立ちます。ただし、複数の単語を検索する必要があります。複数の単語を検索し、1つを除外するようにこれを拡張できますか?
ベストアンサー1
foo
bar
and が含まれているファイル名が欲しいとします。いいえ baz
。この場合:
find . -type f -exec gawk '
BEGINFILE{a=b=c=0}
/foo/{a=1} /bar/{b=1} /baz/{c=1;nextfile}
ENDFILE{if(a && b && !c)print FILENAME}' {} +
[Linuxを使用しているので、すでにGNU awk(gawk)にアクセスできるとします。 ]
このアプローチでは、できるだけ少ない数の awk 呼び出しが開始され、各ファイルは一度だけ読み取られます。中間ファイルは必要ありません。これはうまくいきます。
はい
2つのファイルを含むディレクトリを考えてみましょう。
$ cat file1.eml
foo and
bar only
$ cat file2.eml
foo
and
bar
and
baz
コマンドを実行すると、./file1.eml
要件を満たす唯一のファイルが生成されます。
$ find . -type f -exec gawk '
BEGINFILE{a=b=c=0}
/foo/{a=1} /bar/{b=1} /baz/{c=1;nextfile}
ENDFILE{if(a && b && !c)print FILENAME}' {} +
./file1.eml
どのように動作しますか?
find
一般ファイルのリストを再帰的に収集して渡しますgawk
。BEGINFILE{a=b=c=0}
これにより、各新しいファイルの先頭に変数
a
とb
がc
0(false)に設定されます。/foo/{a=1}
行にが含まれている場合、
foo
変数はa
1に設定されます。 (本物)。/bar/{b=1}
行にが含まれている場合、
bar
変数はb
1に設定されます。 (本物)。/baz/{c=1;nextfile}
行にが含まれている場合、
baz
変数はc
1に設定されます。 (本物)。除外したい単語を見つけたら(
baz
例のように)、ファイルをもう読む必要はありません。だから私たちはnextfile
残りの行をスキップし、すぐにENDFILEに移動します。ENDFILE{if(a && b && !c)print FILENAME}
各ファイルの終わりに if
a
とb
いいえc
(awk の論理!
- ではない) 両方が true の場合、ファイル名を印刷します。
GNUではなくawk
たとえば、awkに良いBEGINFILE
機能がない場合は、各ファイルに対して1つずつ実行する必要があります。ENDFILE
mawk
awk
find . -type f -exec mawk '
/foo/{a=1} /bar/{b=1} /baz/{c=1;exit}
END{if(a && b && !c) print FILENAME}' {} \;
または(ヒント:エドモートン):
awk 'FNR==1 { if (a && b && !c) print fname; fname=FILENAME; a=b=c=0 } /foo/{a=1} /bar/{b=1} /baz/{c=1} END{if(a && b && !c) print FILENAME}' *.eml
または再帰検索を使用してください。
find . -type f -exec awk 'FNR==1 { if (a && b && !c) print fname; fname=FILENAME; a=b=c=0 } /foo/{a=1} /bar/{b=1} /baz/{c=1} END{if(a && b && !c) print FILENAME}' {} +