find … -exec grep … {}\+結果として提供されるファイルを開く安定した方法

find … -exec grep … {}\+結果として提供されるファイルを開く安定した方法

私はしばしば次のコマンドを実行します。

find … -exec grep … --color=always -l {} \+

時にはVimで一致するファイルを開く必要があります。

しかし、最も確実な方法は何ですか?

一方通行そんな気がする

vim $(find … -exec grep … {} \+)

もう一つのアプローチはxargs

これら2つの方法と異なる方法について知る必要がある長所/短所/問題がありますか?

答え1

vim $(find path/ -exec grep -l 'pattern' {} +)

引用符なしのコマンド置換であるため、結果のスペースとパス名の拡張に対してトークン化が行われます。つまり、ファイルがa b一致した場合、Vimは誤って開きますabファイルが* 一致すると、残念ながらそのディレクトリ内のすべてのファイルに展開されます。適切な解決策は

find path/ -type f -exec grep -q 'pattern' {} \; -exec vim {} +

Grepはquietモードで実行されます。各ファイルには戻り値のみが使用されます。その0場合は、ファイル内の一致するものを見つけて、そのファイルをVimに渡します。

{} \;Grep が一度に 1 つのファイルを分析することを示します。{} +すべてのファイルはGrepに引数として渡され、次を使用すると一致するものが見つかります。どのこれらのファイル数に応じて0シャットダウン状態が発生するため、すべてのファイルが Vim で開きます。一方{} +、Vimの場合、見つかった各ファイルは単一のVimプロセスのバッファに保存されます。変化を感じるために変化を試すことができます。

作業速度を上げる必要がある場合:

  • 'pattern'正規表現ではなく固定パターンの場合は、Grap-Fにフラグを追加してください。

  • grep -lZ、Xargs、および特別なシェル構成もプロセスを高速化する必要があります。Stefan Chazerasの答え

そしてここXargs、Find、Vimのもう1つの類似したユースケースです。

答え2

GNUツール(--color=alwaysすでにGNU拡張)とKshスタイルのプロセス交換をサポートするシェルの使用:

xargs -r0a <(grep -rlZ pattern .) vim

または:

xargs -r0a <(find . ... -exec grep -lZ pattern {} +) vim

そしてzsh

vim ${(0)"$(find . ... -exec grep -lZ pattern {} +)"}

4.4+ バージョンbash:

readarray -td '' files < <(find . ... -exec grep -lZ pattern {} +)
vim "${files[@]}"

これにより、grep実行される呼び出しの数が最小限に抑えられます。要点は、出力をNULで区切られたファイル名で指定して、GNUの引数拡張フラグを介して別の引数に確実に分割できるgrepようにすることです。vimxargs -0zsh0bashreadarray -td ''

では、zsh次のこともできます。

vim ./**/*(...e['grep -q pattern $REPLY'])

(ここでは、メソッド...のように追加できる追加修飾子を示しますfind。)

ただし、これは使用された方法と同様に、ファイルごとに1回の呼び出しが実行されるため、速度が大幅に遅くなることを意味しfind -exec grep -q pattern {} ';'ますgrep

zsh--color=alwaysデフォルトから値を変更して変更すると、-Z最初のアプローチが機能します。他のシェルは変数へのNUL保存をサポートしていないため、機能せず、使用または無効にする必要がある分割をもたらす単語のファイル名の生成も実行します。IFSIFS=$'\0'IFS=$' \r\n\0'$IFSset -o noglobset -f

検索結果を繰り返すのはなぜ悪い習慣ですか?find安定して見つかったファイルのリストを処理する方法に関する追加情報を提供します。

答え3

2つの異なる方法:

  1. 結果をクイックフィックスリストに配置します。
find ... -exec grep -Hn {} + >results
vim -q results

または清掃部(shではない)

vim -q <(find ... -exec grep -Hn {} +)
  1. 使用:grep -R:Cfilter:
vim
:grep -R ...
:packadd cfilter
:Cfilter[!]

関連:helpコマンドを参照してください。

:cnextどちらか他のコマンドを使用して一致をナビゲートできます:help quickfix

関連情報