grepを使用するには、txtファイルまたは拡張子のないファイルに複数の文字列が必要です。

grepを使用するには、txtファイルまたは拡張子のないファイルに複数の文字列が必要です。

同時に検索される2つの文字列を持つ.txt拡張子がある場合とない場合のファイルのディレクトリを再帰的に検索したいと思います。この問題にどのように対処する必要がありますか?

たとえば、このディレクトリには、「String1」、「String2」、および「String3」を含む5つのファイルがあります。そのうちの2つは.pdfと.htmlですが興味はありません。残りの3つは.txtファイルまたは拡張子がありません。すべての文字列を含み、拡張子が.txtであるか、拡張子がまったくないパスを取得したいと思います。

ベストアンサー1

修正された質問で更新されました。

find directory -type f \( -name '*.txt' -o ! -name '*.*' \) \
    -exec grep -q -F -e 'string 1' {} \; \
    -exec grep -q -F -e 'string 2' {} \; \
    -exec grep -q -F -e 'string 3' {} \; \
    -print

これは、再帰的に呼び出されるディレクトリ内の名前にドットがない通常のファイルだけでなく、ファイル名のサフィックスを持つ一般的なdirectoryファイルも検索します。.txtそのようなファイルが見つかったら、grep前に説明したのと同様の方法で、3つの文字列がすべてファイルに存在することを確認します(下記参照)。

文字列が見つかると、ファイルのパス名が印刷されます。

または、最初の部分(下)のコードを使用してください。

find directory -type f \( -name '*.txt' -o ! -name '*.*' \) -exec sh -c '
    for pathname do
        if  grep -q -F -e "string 1" "$pathname" &&
            grep -q -F -e "string 2" "$pathname" &&
            grep -q -F -e "string 3" "$pathname"
        then
            printf "All were found in \"%s\"\n" "$pathname"
        fi
    done' sh {} +

また見なさい:


質問を修正する前の前の回答:

Unixはファイル名からファイルタイプを推測しないため、ファイル名は重要ではありません。

というファイルに特定の文字列があるかどうかをテストするには、file次のようにします。

if grep -q -F -e 'some string' file; then
    echo 'The string is present'
else
    echo 'The string is not present'
fi

ここで使用されるオプションgrep

  • -q:静かになりgrep、パターンが一致するとすぐに終了します。パターンに一致する行を抽出するのではなく、一致が見つかったかどうかを反映する終了状態で終了します。この終了ステータスは上記の文で使用されていますif
  • -Fgrepパターンは正規表現ではなく文字列として扱われます。これにより、a * [in the] sky同様の文字列がテキスト内の特殊文字をエスケープしなくてもテキストに表示されるかどうかをテストできます。
  • -e:grep次の引数が一致パターンとして扱われます。これにより、コマンドラインオプションとして考える-必要なく、で始まるパターンを使用できます。grep

複数の文字列をテストするには、grep次のように追加のテストを追加します。

if  grep -q -F -e 'string 1' file &&
    grep -q -F -e 'string 2' file &&
    grep -q -F -e 'string 3' file
then
    echo 'All three string were found in the file'
else
    echo 'One or more string was not found in the file'
fi

たとえば、名前付き配列を持つシェルを使用すると、配列bashに文字列を格納し、次のループを実行することもできます。

strings=( 'string 1' 'string 2' 'string 3' )

found=true
for string in "${strings[@]}"; do
    if ! grep -q -F -e "$string" file; then
        found=false
        break
    fi
done

if "$found"; then
    echo 'All strings were found'
else
    echo 'Not all strings were found'
fi

これは文字列を繰り返し、そのうちの1つはいいえ検出(!テスト結果を否定することに注意してくださいgrep)し、変数をfound設定してfalseループを終了します(追加の文字列をテストする必要はありません)。

$foundその後、それがまたはtrue認知テストしfalse、そのテスト結果に基づいてアクションを実行します。

上記のシェルコードは、次のように書き直されました/bin/sh(名前付き配列なし)。

set -- 'string 1' 'string 2' 'string 3'

found=true
for string do
    if ! grep -q -F -e "$string" file; then
        found=false
        break
    fi
done

if "$found"; then
    echo 'All strings were found'
else
    echo 'Not all strings were found'
fi

おすすめ記事