私はLinux Ubuntu 18.04と20.04を使用しています。
Ripgrep( rg
) は、次のように一致を含むファイルのパスのリストを出力できます。
# search only .txt files
rg 'my pattern to match' -g '*.txt' -l
# long form
rg 'my pattern to match' --glob '*.txt' --files-with-matches
出力は次のとおりです。
path/to/file1.txt path/to/file2.txt path/to/file3.txt
など。
tree $(dirname $PATH)
次に、各パスで異なるコマンドを実行して、一致するファイルを含むディレクトリ内のすべてのファイルのリストを取得したいと思います。どうすればいいですか?
xargs
それが答えの一部になるかもしれませんか?しかし、xargs
このようなパイプラインで始めると、最後に印刷されたファイルだけを処理するようです。
rg 'my pattern to match' -g '*.txt' -l | xargs -0 -I {} dirname {}
注:Tooを使用してデモンストレーションできる場合は、ripgrepを持ってgrep
いない人にも役立ちます。ripgrep
インストールはとても簡単です。。
引用:
ベストアンサー1
GNUシステムでは、次のように見えます。
rg -g '*.txt' -l0 'my pattern to match' | # list files NUL-delimited
xargs -r0 dirname -z -- | # takes dirnames
LC_ALL=C sort -zu | # remove duplicates
xargs -r0 tree --
両方dir/file.txt
が一致すると、両方で実行されるため、dir/subdir/file.txt
内容は2回表示されます。tree
dir
dir/subdir
dir/subdir
あなたの考えは正しいです。xargs
which isコマンドを使用してバイト文字列をパラメータリストに変換してコマンドに渡し、-0
whichを使用すると、任意のパラメータリストを渡す最も信頼性の高い方法になります。
xargs -0
入力は、パラメーター・リストがNUL文字(0バイト)で区切られた形式であると予想されます。この形式でファイルリストを印刷するには、-0
/オプションが必要です。--null
rg
- GNUは
dirname
呼び出しごとに複数の引数を処理できるため、-I{}
これを使用する代わりにすべての引数を渡します。また、ファイルのリストが空の場合、それをまったく呼び出さずに-r
NULで区切られたディレクトリを印刷するオプション自体もGNUに対応します。dirname
-z
dirname
dirname
- 各ファイルにはプレフィックスが付いていないため、ファイル名の前に s が付く問題を回避するために、ファイルのリストを引数として渡すコマンドに
rg
オプションの区切り./
文字を使用することが重要です。--
-
簡単に言うと、値がNULではなくバイトシーケンス(ファイルパスや任意のコマンド引数など)になる可能性があるリストの場合、NULで区切られたレコードを交換形式で使用するツールとツールの間でプログラムでリストを渡そうとします。 。人間の形式でのみユーザーにフィードバックを提供します(ここではツリー出力tree
)。
GNU以外のシステムでは、zsh
シェルを使用して次のことができます。
files=( ${(0)"(rg -g '*.txt' -l0 'my pattern to match')"} )
typeset -U unique_dirs=( $files:h )
(( $#unique_dirs )) && tree -- $dirs
または一度に(一致するファイルが1つ以上あると仮定):
tree -- ${(u)${(0)"$(rg -g '*.txt' -l0 'my pattern to match')"}:h}
u
(nique u
)交換しましたtypeset -U
。パラメータ拡張フラグは、NULで分割するように0
指示する方法です。あるいはzsh
、IFS=$'\0'
トークン化を設定して使用することもできます(引用符なしの引数拡張中に実行されます)。
IFS=$'\0'
tree -- ${(u)$(rg -g '*.txt' -l0 'my pattern to match'):h}
GNUユーティリティもGNUユーティリティもない場合は、zsh
いつでも次のものを使用できますperl
。
rg -g '*.txt' -l0 'my pattern to match' |
perl -MFile::Basename -MList::Util=uniq -0 -e '
@dirs = uniq(map {dirname$_} <>);
exec "tree", "--", @dirs if @dirs'
¹これは、コマンド引数には表示できない唯一の文字/バイト値です(引数は、execve()
システムコールからNULで区切られた文字列に渡されるため)。しかし、パイプを介して供給されるバイトストリームには現れる可能性があるので、単純で明確です。任意のパラメータを分離する方法です。-0
GNU実装の非標準的な拡張ですが、他の多くの実装xargs
でも見つけることができます。
²または少なくとも1回の通話に入ることができるだけ、dirname
必要なだけ通話してください。