globと再帰的に一致するスペースで区切られ、エスケープされたファイルのフルパスを設定するには?

globと再帰的に一致するスペースで区切られ、エスケープされたファイルのフルパスを設定するには?

パラメータとしてファイルパスを要求するプログラムがあります。このパスは引用できず、作業ディレクトリに依存できません。複数の、、、、xargssを接続せずにこれを実行できますか?trfindreadlink

"*.csv"ファイルの出力例:/home/user/a\ b.csv /home/user/my\ dir/c\ d\$2.csv

答え1

ファイルパスをコマンドに引数として渡すには、find自分でやろう-execオプショントリックなしxargs:

find /home/user -name '*.csv' -exec yourcommand '{}' +

その後、呼び出されたすべてのファイルを見つけて、見つかったすべての*.csvファイルを引数として実行します。見つかった各ファイルは個別の完全引数でプログラムに渡されるため、エスケープやその他の操作は必要ありません。各引数は、フルファイルパスである多くの引数を使用します。/home/useryourcommand /home/user/a\ b.csv /home/user/my\ dir/c\ d\$2.csv ...yourcommand

別の方法はシェル(zsh特に)は、次のように作成できる高度なワイルドカードをサポートします。

yourcommand **/*.csv

上記の効果も得られます。


文字列自体を本当にエスケープしたい場合、コマンドを直接実行する代わりにbash'を使用できます。組み込みprintf:

find /home/user -name '*.csv' -exec bash -c 'printf "%q " "$@"' dummy '{}' +

書式%q指定は、文字列引数のシェルエスケープバージョンに拡張されます。多くのパラメータでは、printfフォーマット文字列がすべてのパラメータに対して繰り返されるため、コマンド内のすべてのパラメータに対してスペースで終わるエスケープ文字列が生成されますbash -cdummyの値として使用$0し、(完全)ファイル名である残りの引数をすべて"$@"指定します。printfあなたの例では正確に/home/user/a\ b.csv /home/user/my\ dir/c\ d\$2.csv

答え2

そしてzsh

print -r -- **/*.csv(D:a:q)

改行、タブ、印刷できない文字などの一部の文字は記号を使用してレンダリングされるため、$'...'問題になる可能性があります。

別の方法は次のとおりです。

print -r -- *.csv(e/'REPLY=${(qq)REPLY:a}'/)

すべてのファイルパスは一重引用符で囲まれています。

関連情報