web-dev-qa-db-ja.com

内部に特定のテキストと特定の拡張子を持つファイルを見つける方法は?

UNIXの場合:フォルダには、拡張子が.sas(プログラム)のファイルと.sas7bdat(テーブル)のファイルがあります。 「liasse」というテキストを含むプログラム(テーブルではない)を見つける必要があります。このコマンドを起動してみました:

grep -rli liasse *.sas ./

その結果、テーブル名が表示されます。プログラムのみを取得するコマンドはどうあるべきですか?

4
Nasser

これは、POSIX準拠のコマンドであり、一度に多くのファイルに対してgrepを起動します。

find . -type f -name '*.sas' -exec grep -li liasse {} +


コマンドgrep -rli liasse *.sas ./が期待どおりに機能しません。何が起こるかを分析しましょう:

  1. *.sasはシェルグロブを受けます。
    1. 現在のディレクトリに*.sasに一致するオブジェクトが少なくとも1つある場合、それらはすべてliasseの後に配置されます。
    2. そのようなオブジェクトがない場合、grepは、検査対象のパスとしてリテラル*.sasを取得し(状況によって異なります。たとえば、bashshopt -s nullglobshopt -s failglobを調査します)、警告をスローする場合があります。
  2. いずれにせよ、grep./を取得し、ファイル内のliasseの検索でそれを再帰的に処理します。これにより、./の下にあるすべてのファイルが処理されます:プログラム、テーブルなど。

そのため、結果にテーブル名を含めることができます。


私のコマンドfind . -type f -name '*.sas' -exec grep -li liasse {} +は、*.sasパターンに一致するファイルに対してのみgrepを実行します。重要な事柄:

  • -type fはファイルのみを選択します。このようにして、ディレクトリ名*.sas(存在する場合)と一致することがgrepに渡されないようにします(-rなしのgrepはとにかくそれらを拒否する必要がありますが、エレガントではありません) 。
  • パターンを引用すると、シェルがグロブするのを防ぎます。 findは、*.sasオペランドの引数としてリテラル-nameを取得します。このようなパターンを解釈する方法を知っています。
  • find … -exec … {} +構文は、{}の代わりに複数のオブジェクトを置き換えます。このようにして、find … -exec … {} \;と比較して、作成されるgrepプロセスが少なくなります(おそらく1つだけ)。
2

findコマンドを使用して、名前ですべてのファイルを再帰的に検索し、各ファイルに対してgrepを実行できます。最も簡単な解決策は、findの-execオプションを使用することです。

find . -name '*.sas' -exec grep -li liasse {} \;

または、findxargsを組み合わせることができます。

find . -name '*.sas' -print0 | xargs -0 grep -li liasse

これは、すべての単一ファイルではなく、ファイルの大きなバッチに対してgrepを実行するため、パフォーマンスがわずかに向上します。

xargs-Pオプションを使用すると、複数のgrep呼び出しを並行して実行することもできます。

1
vog