1

私はシェルスクリプトを持っています

find . -name "*.java" -print0 | xargs -0 grep -Lz 'regular_expression'

この方法で正規表現に一致しないファイル名を出力します。

file1.java
file2.java
...

私が理解している方法では、次のように機能します。find必要なファイルを見つけて、それらの名前を\0. 次にwithxargsの出力を分割し、それらを1 つずつフィードします。find\0grep

basename次に、ステージをもう 1 つ追加して、ファイルのみを取得したいと考えました。スクリプトを変更しました:

find . -name "*.java" -print0 | xargs -0 grep -LzZ 'regular_expression' | xargs -0 basename

しかし、エラーが発生しました。調査を開始し、一時的な出力を作成しました。

find . -name "*.java" -print0 | xargs -0 grep -LzZ 'regular_expression' | xargs -0  echo basename

そしてこれを得ました:

basename ./file1.java ./file2.java ./subdir/file1.java ./subdir/file2.java

そのため、ファイル名は\0. xargswith で使用され、 withでgrep分割されていない場合に、なぜそれらが分割されるのかわかりません。xargsbasename

-n1後者で使用して回避策を得ましたxargsxargsしかし、なぜそれが必要なのか ( withで in を使用しなかった場合grep) と、このパラメーターが何をするのかはまだわかりません。

-n1後者の使用法では何が必要で、前者の使用法では必要なかった理由を説明していただければ幸いですgrep

4

2 に答える 2

6

-n1指定されたコマンドを引数ごとに 1 回実行するように指示xargsします

したがって、次のようなものがある場合

echo file1 file2 file2 | xargs basename

それは同等です

basename file1 file2 file2

しかし、もしそうなら

echo file1 file2 file2 | xargs -n1 basename

これにより、xargs が実行されます。

basename file1 
basename file2 
basename file2

xargs-0フラグについては、デフォルトの空白の代わりに分割するよう--nullに指示するオプションのエイリアスです。find を で入力したため、 の後に必要でしたが、 の結果はプレーンな空白で区切られたトークンです。xargs\0find\0-print0grep

于 2013-01-18T18:23:13.393 に答える
2

ファイル名\0. 違いは、使用しているコマンドにあります。 xargs通常、標準入力を受け取り、それをリストに分割し (ここでは NUL で分割)、そのリストを追加の引数としてコマンドに渡します。したがって、これを行うと:

find . -name "*.java" -print0 | xargs -0 grep -Lz 'regular_expression'

実際に実行されるのは次のとおりです。

grep -Lz 'regular_expression' file1.java file2.java file3.java...

ここでは、標準入力の読み取り-z方法にのみ影響grepし、標準入力には何も送信していないため、重要ではありません。

xargsしたがって、 を実行する別のものを追加すると、次のbasenameようになります。

basename file1.java file2.java file3.java...

しかし、 whilegrepは任意の数のファイル名引数を取り、 basename1 つだけを取り、他は無視します。

ここで、引数のリストを (1 つの) チャンクに分割し、コマンドを複数回実行するように指示します-n 1xargsしたがって、現在実行されているのは次のとおりです。

basename file1.java
basename file2.java
basename file3.java
...

そして、すべての出力が stdout に連結されます。

于 2013-01-18T18:23:20.177 に答える