まず、マイナーだが適用できない答えを切り取ります。呼び出しごとにこれらの式をほとんど使用する必要があるため、find
+xargs
トリックやそのバリアント(find
withなど)は使用できません。-exec
最後にこのトピックに戻ります。
では、より良い例として、次の点を考えてみましょう。
$ find -L some/dir -name \*.abc | sort
some/dir/1.abc
some/dir/2.abc
some/dir/a space.abc
パラメータとしてどのように渡しますかprogram
?
これで問題は解決しません
$ ./program $(find -L some/dir -name \*.abc | sort)
program
次のパラメータを取得したため失敗しました。
[0]: ./program
[1]: some/dir/1.abc
[2]: some/dir/2.abc
[3]: some/dir/a
[4]: space.abc
見てわかるように、空白のあるパスは分割され、program
2つの異なるパラメータとして扱われます。
有効日までの見積もり
私のような初心者ユーザーは、これらの問題に直面したときに最終的に動作するまでランダムに引用符を追加する傾向があるようです。ここでは役に立たないようです...
"$(…)"
$ ./program "$(find -L some/dir -name \*.abc | sort)"
[0]: ./program
[1]: some/dir/1.abc
some/dir/2.abc
some/dir/a space.abc
引用符は単語の区切りを防ぐので、すべてのファイルは単一の引数として渡されます。
別のルート参照
有望なアプローチ:
$ ./program $(find -L some/dir -name \*.abc -printf '"%p"\n' | sort)
[1]: "some/dir/1.abc"
[2]: "some/dir/2.abc"
[3]: "some/dir/a
[4]: space.abc"
もちろん引用文もあります。しかし、これ以上説明しない。それらは文字列の一部にすぎません。それで彼らは噴射を止めなかっただけでなく、議論も行いました!
IFSの変更
それから私は遊んでみましたIFS
。とにかく私は「有線経路」自体で問題を引き起こさないようにfind
with-print0
とsort
with -を好みます。それでは、役割分割を強制してすべてを整えるのは-z
どうでしょうか?null
$ ./program $(IFS=$'\0' find -L some/dir -name \*.abc -print0 | sort -z)
[0]: ./program
[1]: some/dir/1.abcsome/dir/2.abcsome/dir/a
[2]: space.abc
したがって、それはまだ空間的に分割されており、垂直に分割されていませんnull
。
私は(上記のように)IFS
beforeとbeforeに課題を入れました。私はwith、with、withoutなどの他の構文も試しました。これらのどれも何の違いもないようです。$(…)
./program
\0
\x0
\x00
'
"
$
今アイデアがなくなりました。もう少し試してみましたが、すべて同じ問題がリストされているようです。
私はまた何ができますか?これは可能ですか?
もちろん、program
受け入れモードを作成して直接検索することもできます。ただし、これを特定の構文に変更するには、多くの二重操作が必要です。 (grep
たとえば、aを介してファイルを提供するのはどうですか?)
program
また、パスのリストを含むファイルを許可することもできます。その後、find
式を一時ファイルに簡単にダンプし、そのファイルへのパスを提供できます。これは、ユーザーが単純なパスのみを持っている場合は、中間ファイルなしで提供できるように直接パスに従うことをサポートできます。ただし、これはビューには適していません。追加の実装が必要なことは言うまでもなく、追加のファイルを生成して処理する必要があります。 (しかし、利点は、引数であるファイルの数がコマンドラインの長さの問題を引き起こし始める場合に役立ちます...)
最後に、私の場合は、find
+(および同様の)トリックが機能しなかったことをもう一度思い出させます。xargs
説明を簡単にするために、1つのパラメータのみを表示します。しかし、私の実際のケースは次のとおりです。
$ ABC_FILES=$(find -L some/dir -name \*.abc | sort)
$ XYZ_FILES=$(find -L other/dir -name \*.xyz | sort)
$ ./program --abc-files $ABC_FILES --xyz-files $XYZ_FILES
だから、1つを検索してももう1つxargs
はどうすればいいのか気になります。
ベストアンサー1
配列を使用してください。
ファイル名に改行の可能性を処理する必要がない場合は、エスケープできます。
mapfile -t ABC_FILES < <(find -L some/dir -name \*.abc | sort)
mapfile -t XYZ_FILES < <(find -L other/dir -name \*.xyz | sort)
それから
./program --abc-files "${ABC_FILES[@]}" --xyz-files "${XYZ_FILES[@]}"
もしあなたならするファイル名の改行を処理する必要があり、bash> = 4.4の場合は、配列の構成中に名前をnullで終了するためにおよびを-print0
使用できます。-d ''
mapfile -td '' ABC_FILES < <(find -L some/dir -name \*.abc -print0 | sort -z)
(それも似ていますXYZ_FILES
)。もしあなたならいいえ最新のbashを使用すると、nullで終わる読み取りループを使用してファイル名を配列に追加できます。
ABC_FILES=()
while IFS= read -rd '' f; do ABC_FILES+=( "$f" ); done < <(find -L some/dir -name \*.abc -print0 | sort -z)