web-dev-qa-db-ja.com

1つの単語を含み、2番目の単語を含まないファイルを検索するシェルコマンド

すべて

Linuxマシンに以下の2つのファイルがあり、「Word1」を含み「Word99」を含まないファイルを見つけたいと思いました。

file1.txt
  Word1
  Word2
  Word3
  Word4
  Word5

file2.txt
  Word1
  Word2
  Word3
  Word99

「Word1」を含むファイルに対して以下のコマンドを使用していますが、「Word1」を含むが「Word99」を含まないファイル名を取得するように変更する方法に関する情報が見つかりませんでした

find . -name '*.*' -exec grep -r 'Word1' {} \; -print > output.txt

どんなポインタも役に立ちます。

サンディありがとう

5
Sandeep K Gujje
    $ grep -lr 'Word1' * | xargs grep -L 'Word99'
    file1.txt

どこ:

    -l, --files-with-matches
         Only the names of files containing selected lines are written
         to standard output.
    -R, -r, --recursive
         Recursively search subdirectories listed.
    -L, --files-without-match
         Only the names of files not containing selected lines are written
         to standard output.

パイプの前のコマンドの最初の部分では、次のようになります。

    $ grep -lr 'Word1' * 
    file1.txt
    file2.txt

上記のコマンドは、サブディレクトリ内のファイルを再帰的に解析し、Word Word1、つまりfile1.txtfile2.txtを含むファイルを一覧表示します。

後の2番目の部分| xargs grep -L 'Word99'で、パイプはfile1.txtfile2.txtを入力としてxargsに送信し、引数としてgrepに提供します。次に、grepは、Word99オプション、つまり-Lを使用して、file1.txtを含まないファイルを一覧表示します。

コマンドの最初の部分で、stdoutの出力としてfile1.txtfile2.txtを取得するため、ここではxargsが必要です。文字列file1.txtおよびfile2.txtではなく、これらのファイルの内容を解析する必要があります。

次のコマンドでも同じ結果が得られます(文字列の検索/除外の方法が逆になります)。

      $ grep -Lr 'Word99' * | xargs grep -l 'Word1'
      file1.txt
5
Santios

質問のタイトルには、単語を「含むファイル」と記載されています。しかし、あなたの質問では、Wordを「含むファイル名を取得する」と述べています。これらは別のものです。幸い、どちらもかなり単純なので、両方を簡単に紹介します。

Wordを含むファイルを検索するには:

grep -iR "Word1"。

-iは大文字と小文字を区別しないように言います。 -Rは再帰的です(サブディレクトリが検索されることを意味します)。 (大文字はOpenBSDによって文書化されており、lsに似ているので、-rよりも優先します。)ピリオドは、どこから検索を開始するかを指定します。

Wordを含むファイル名を検索するには:

見つける。 -iname "Word1"

-inameは、大文字と小文字を区別しないバージョンの「name」です。

期間は、どこから探し始めるかを指定します。多くの場合、現在のディレクトリが適切な選択です。

注:例の1つで「 "」を参照しました。これはDOSには最適で、通常はMicrosoft Windowsには適していますが、Unix環境には非常に悪い習慣です。それを見ると、あなたはWindowsに精通していると思います。 Windowsでは、「FIND」(または「find」)がファイル内のテキストを検索することを理解してください。 Unixは異なります。「grep」はファイル内のテキストを検索し、「find」はファイル名を検索します。

ここで、Word 99を除外し、それをテキストファイルに配置するには、次のテキストを追加します。

| grep -v Word99 >> output.txt

これはパイプキーであり、ほとんどの場合Shift-Backslashです。

したがって、例として、両方を実行したい場合は、次を使用します。

grep -iR "Word1"。 | grep -v Word99 >> output.txt
検索。 -iname "Word1" | grep -v Word99 >> output.txt

パイプ文字の前の部分はコマンドを実行し、出力をUnixスタイルのパイプに送信します。次に、コンテンツはパイプから次のコマンドの標準入力に送信されます。 grep -vは、受け取った標準入力を調べて、必要なものを除外します。 grep -vは、残りの結果を標準出力に送信します。 >>は、前のコマンドの標準出力を指定されたテキストファイルの末尾にリダイレクトします。

テキストを除外する方法について、「find」コマンドに文書化されたオプションが表示されない理由は、Unixが非常に重く設計されており、より単純なプログラムを作成し、パイピング技術を使用して精巧な効果を生み出すという考えに基づいているためです。 Microsoft環境では、古いMicrosoftコードはパイプ処理が特に面倒だったため、プログラムは基本的に各プログラムにより多くの機能を組み込むことを試みました。一方で、これはエンドユーザー(すべてが組み込まれている)にとっては簡単に思えますが、そのアプローチには一貫性がありません。 Unixを使用しているときは、パイピングを恐れないでください。慣れると、作業が大幅に簡素化されることに気付くかもしれませんが、多くの状況で簡単なツールを使用できるため、必要ありません。簡単なテクニックを何度も何度も再学習します(異なるプログラムごとに)。

0
TOOGAM

これにより、Word1を含むファイルが検索されます。

$ find . -name '*.*' -type f -exec grep -q 'Word1' {} \; -print
./file1.txt
./file2.txt

これにより、Word1を含むがnotWord99を含むファイルが検索されます。

$ find . -name '*.*' -type f -exec grep -q 'Word1' {} \; '!' -exec grep -q 'Word99' {} \; -print 
./file1.txt

出力をファイルに保存するには:

find . -name '*.*' -type f -exec grep -q 'Word1' {} \; '!' -exec grep -q 'Word99' {} \; -print >output.txt

テスト-exec grep -q Word99 {} \;は、Word99のファイルに対してTrueを返します。その前に!を付けて、戻り値を無効にします。したがって、! -exec grep -q Word99 {} \;は、Word99を持つnotファイルに対してTrueを返します。 !は一重引用符で囲まれています。これは、履歴拡張がオンになっている場合、!がシェルアクティブ文字になる可能性があるためです。

ノート:

  1. -qオプションがgrepに追加され、静かになりました。 -qを使用すると、grepは正しい終了コードを設定しますが、stdoutに一致する行を表示しません。

  2. -type fテストがfindに追加され、通常のファイルの名前のみが返されるようになりました。

0
John1024