web-dev-qa-db-ja.com

一部のファイルにスペースが含まれている場合、ファイルのグループで文字列を検索するにはどうすればよいですか?

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」です。検索対象のファイルにスペースが含まれている場合でも、上記のコマンドを正常に実行するにはどうすればよいですか。

3
Dave A

findxargs出力を使用する場合、 推奨される方法 は、NUL文字を使用して各ファイル名を区切ることです。

find src/main -name "*" -print0 | xargs -0 grep -i 'mystring'

この理由は、シェル(および具体的にはxargs)は一般的に 引数を分割 (またはxargsの場合は入力)空白、つまりスペース、タブに基づいているためです。 、および改行。 -0を使用すると、xargsNULで区切られた各フィールドを読み取ります。これはfind -print0が出力するものです。

これは、GNU findxargs、およびOS Xに含まれているバージョンで機能します。他のバージョンには、必須ではないため、オプションがない場合があります。 POSIXで。


しかし、繰り返しになりますが、これは実際には必要ありません。 "*"の名前パターンは、考えられるすべての名前に展開されます。 grepはそれ自体で再帰できるため、必要なのは次のとおりです。

grep -ri 'mystring' src/main

Bash 4(デフォルトではOS Xに付属していません)では、再帰的なグロブを実行することもできます。すべての.txtファイルに対して globstarオプション を使用:

shopt -s globstar
grep -i 'mystring' **/*.txt
4
slhck

この種のことを行う最も安全で簡単な方法は、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' {} +
2
terdon