Mac10.7.5を実行しています。ターミナルでは、このコマンドを使用して文字列を含むファイルを検索します
find src/main -name "*" | xargs grep -i 'mystring'
ただし、ファイルにスペースが含まれていると、次のような結果が得られます。
grep: images/mystuff/essential-questions-selected-arrow-ela: No such file or directory
grep: 5.24.38: No such file or directory
grep: PM.png: No such file or directory
上記の例の実際のファイルは「essential-questions-selected-arrow-ela5.24.38PM.png」です。検索対象のファイルにスペースが含まれている場合でも、上記のコマンドを正常に実行するにはどうすればよいですか。
find
でxargs
出力を使用する場合、 推奨される方法 は、NUL
文字を使用して各ファイル名を区切ることです。
find src/main -name "*" -print0 | xargs -0 grep -i 'mystring'
この理由は、シェル(および具体的にはxargs
)は一般的に 引数を分割 (またはxargs
の場合は入力)空白、つまりスペース、タブに基づいているためです。 、および改行。 -0
を使用すると、xargs
はNUL
で区切られた各フィールドを読み取ります。これはfind -print0
が出力するものです。
これは、GNU find
とxargs
、およびOS Xに含まれているバージョンで機能します。他のバージョンには、必須ではないため、オプションがない場合があります。 POSIXで。
しかし、繰り返しになりますが、これは実際には必要ありません。 "*"
の名前パターンは、考えられるすべての名前に展開されます。 grep
はそれ自体で再帰できるため、必要なのは次のとおりです。
grep -ri 'mystring' src/main
Bash 4(デフォルトではOS Xに付属していません)では、再帰的なグロブを実行することもできます。すべての.txt
ファイルに対して globstar
オプション を使用:
shopt -s globstar
grep -i 'mystring' **/*.txt
この種のことを行う最も安全で簡単な方法は、findの-exec
オプションを使用することです。 man find
から:
-exec utility [argument ...] ;
True if the program named utility returns a zero value as its exit status.
Optional arguments may be passed to the utility. The expression must be
terminated by a semicolon (``;''). If you invoke find from a Shell you
may need to quote the semicolon if the Shell would otherwise treat it as a
control operator. If the string ``{}'' appears anywhere in the utility
name or the arguments it is replaced by the pathname of the current file.
Utility will be executed from the directory from which find was executed.
Utility and arguments are not subject to the further expansion of Shell
patterns and constructs.
-exec utility [argument ...] {} +
Same as -exec, except that ``{}'' is replaced with as many pathnames as
possible for each invo-cation invocationcation of utility. This behaviour
is similar to that of xargs(1).
言い換えると、-exec
オプションは、検索結果で指定したものを実行し、{}
を見つかった各ファイル(またはディレクトリ)に置き換えます。したがって、特定の文字列をgrepするには、次のようにします。
find src/main -name "*" -exec grep -i 'mystring' {} +
ただし、ディレクトリも検索され、エラーが発生します。これは機能します。ディレクトリで実行しようとすると文句を言うだけです。xargs
を使用しても同じ問題が発生します。ここで実際に実行しようとしているのは、すべてのファイルとファイルのみを検索することです。その場合、-name '*'
はfind src/main
とまったく同じであるため、find src/main -name "*"
は必要ありません。したがって、それを使用する代わりに、ファイルのみを検索するように指定します。
find src/main -type f -exec grep -i 'mystring' {} +