この xargs マルチコマンドで括弧を処理します。

この xargs マルチコマンドで括弧を処理します。

次の質問にはすでに回答があるようですが、質問の用語を知らず、既存の回答を見つけるのに十分です。

私はファイルのリストを繰り返し、各行にファイル名とPで始まる行数を出力するコマンドを書いています。これまで私は以下を持っています:

find -type f | xargs -I % sh -c '{ echo %; grep -P "^P \d+" % | wc -l; }  | tr "\n" ","; echo ""; '

(実際のfindコマンドはもう少し複雑ですが、簡単に言えば、このコマンドを実行したディレクトリツリーで約11,000個の関心ファイルを見つけました。)

このコマンドは私の目的に対して約98%動作しますが、名前に角かっこを持つファイルの少数があることがわかりました。

その結果、以下の事例を受けました。

sh: -c: line 0: syntax error near unexpected token `('

括弧はシェル特殊文字であることがわかります。たとえば、名前に括弧を含む単一のファイルに対してgrepを直接実行する場合は、ファイル名を一重引用符で囲むか、括弧をエスケープする必要があります。 grep呼び出しで一重引用符の中に「%」を入れることができるように、コマンドで引用符の種類(一番外側の二重引用符、内側の一重引用符)を置き換えようとしましたが、役に立ちませんでした。

find -> xargs -> shsh呼び出しで括弧が正しく処理されるようにチェーンの括弧を処理する方法はありますか?

答え1

データ(ファイル名)をコード(シェルスクリプトレット)に直接含めないことをお勧めします。代わりに、xargs実行しているシェルにファイル名を引数として渡してください。

find -type f | xargs -I % \
  sh -c '{ echo "$1"; grep -c -P "^P \d+" "$1"; } | tr "\n" ","; echo' sh %

grep -cまた、代わりに使用できる必要がありますgrep | wc -l。これにより、少なくともコマンドが少し短くなります。

答え2

.から省略したのでGNUのようfind . -type fです。これにより、次のことができます。findfind

find . -type f -printf %p, -exec grep -cP '^P \d' {} ';'

ファイルパスに:文字が含まれていない場合は、次のこともできます(GNUを使用grep)。

grep -rcP '^P \d' . | tr : ,

:文字が含まれているが改行文字が含まれていない場合は、行の最後の:文字のみを置き換えることでこの問題を解決できます,

grep -rcP '^P \d' . | LC_ALL=C sed 's/\(.*\):/\1,/'

この方法は、次の用途にも使用できます。

find ... -type f -exec grep -cHP '^P \d' {} + | ...

findたとえば、より多くの選択基準があるため、まだ使用する必要がある場合。

答え3

イカチュの答え良い改善になったようで、おそらく何をすべきかわかりません。

情報を提供するためのより軽いタッチ修正を追加して、問題が何であるかを示します。

find -type f | xargs -I % sh -c '{ echo "%"; grep -P "^P \d+" "%" | wc -l; }  | tr "\n" ","; echo ""; '

%デフォルトでは - 置き換える項目への参照です。

関連情報