次の質問にはすでに回答があるようですが、質問の用語を知らず、既存の回答を見つけるのに十分です。
私はファイルのリストを繰り返し、各行にファイル名と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 -> sh
sh呼び出しで括弧が正しく処理されるようにチェーンの括弧を処理する方法はありますか?
答え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
です。これにより、次のことができます。find
find
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 ""; '
%
デフォルトでは - 置き換える項目への参照です。