Linuxのfind
コマンドで正規表現を使用して巨大なディレクトリツリーに再帰的に飛び込み、すべての.c、.cpp、および.hファイルを表示しますが、特定のサブストリングを含む一致を省略します。xargs
最終的には、一致するすべてのファイルに対して特定の処理を実行するコマンドに出力を送信したいと思います。grepを介して出力をパイプ処理してfind
、これらのサブ文字列を含む一致を削除することはできますが、そのソリューションは、スペースを含むファイル名ではうまく機能しません。そこでfind
、改行(空白)の代わりにヌル文字で各ファイル名を終了する's -print0オプションを使用してみました。またxargs -0
、スペース区切りの入力の代わりにヌル文字の入力を期待するために使用しましたが、その方法がわかりませんでした。ヌル区切りを渡すfind
パイプされたgrepフィルターを正常に通過します。grep -Zは、その点では役に立たなかったようです。
だから私は、より良い正規表現を書いてfind
、中間grep
フィルターを廃止するだけだと思いました...おそらくsed
代替案でしょうか?
いずれにせよ、次のディレクトリの小さなサンプリングでは...
./barney/generated/bam bam.h
./barney/src/bam bam.cpp
./barney/deploy/bam bam.h
./barney/inc/bam bam.h
./fred/generated/dino.h
./fred/src/dino.cpp
./fred/deploy/dino.h
./fred/inc/dino.h
...出力にすべての.h、.c、および.cppファイルを含めたいのですが、「生成された」および「デプロイ」ディレクトリに表示されるファイルは含めないでください。
ところで、この行全体をbashシェルにカットアンドペーストすることで、この質問のソリューションをテストするためのテストディレクトリ全体(fredbarneyという名前)を作成できます。
mkdir fredbarney; cd fredbarney; mkdir fred; cd fred; mkdir inc; mkdir docs; mkdir generated; mkdir deploy; mkdir src; echo x > inc/dino.h; echo x > docs/info.docx; echo x > generated/dino.h; echo x > deploy/dino.h; echo x > src/dino.cpp; cd ..; mkdir barney; cd barney; mkdir inc; mkdir docs; mkdir generated; mkdir deploy; mkdir src; echo x > 'inc/bam bam.h'; echo x > 'docs/info info.docx'; echo x > 'generated/bam bam.h'; echo x > 'deploy/bam bam.h'; echo x > 'src/bam bam.cpp'; cd ..;
このコマンドは、すべての.h、.c、および.cppファイルを検索します。
find . -regextype posix-egrep -regex ".+\.(c|cpp|h)$"
...しかし、出力をxargsにパイプすると、'bam bam'ファイルはそれぞれ2つの別々の(存在しない)ファイル名として扱われます(ここではls
、実際にやりたいことの代用として使用していることに注意してください)出力):
$ find . -regextype posix-egrep -regex ".+\.(c|cpp|h)$" | xargs -n 1 ls
ls: ./barney/generated/bam: No such file or directory
ls: bam.h: No such file or directory
ls: ./barney/src/bam: No such file or directory
ls: bam.cpp: No such file or directory
ls: ./barney/deploy/bam: No such file or directory
ls: bam.h: No such file or directory
ls: ./barney/inc/bam: No such file or directory
ls: bam.h: No such file or directory
./fred/generated/dino.h
./fred/src/dino.cpp
./fred/deploy/dino.h
./fred/inc/dino.h
find
したがって、-print0および-0引数を使用してこれを拡張できますxargs
。
$ find . -regextype posix-egrep -regex ".+\.(c|cpp|h)$" -print0 | xargs -0 -n 1 ls
./barney/generated/bam bam.h
./barney/src/bam bam.cpp
./barney/deploy/bam bam.h
./barney/inc/bam bam.h
./fred/generated/dino.h
./fred/src/dino.cpp
./fred/deploy/dino.h
./fred/inc/dino.h
...これは素晴らしいことですが、出力に「生成された」ディレクトリと「デプロイ」ディレクトリが必要ない点が異なります。だから私はこれを試してみます:
$ find . -regextype posix-egrep -regex ".+\.(c|cpp|h)$" -print0 | grep -v generated | grep -v deploy | xargs -0 -n 1 ls
barney fred
...明らかに機能しません。そこで、grepで-Zオプションを使用してみましたが(-Zオプションが実際に何をするのか正確にはわかりません)、それも機能しませんでした。だから私はもっと良い正規表現を書くと思いました、find
そしてこれは私が思いつくことができる最高のものです:
find . -regextype posix-egrep -regex "(?!.*(generated|deploy).*$)(.+\.(c|cpp|h)$)" -print0 | xargs -0 -n 1 ls
...しかし、bashはそれを気に入らなかった(!。*:イベントが見つかりません、それが何を意味するのか)、そしてそれが問題ではなかったとしても、私の正規表現は私が通常使用している正規表現テスターのWebページでは機能しないようです使用する。
これを機能させる方法はありますか?これは私が望む出力です:
$ find . [----options here----] | [----maybe grep or sed----] | xargs -0 -n 1 ls
./barney/src/bam bam.cpp
./barney/inc/bam bam.h
./fred/src/dino.cpp
./fred/inc/dino.h
...そして、スクリプトと一時ファイルは避けたいと思います。これが私の唯一の選択肢かもしれません。
前もって感謝します!-マーク