これで問題は解決しません

これで問題は解決しません

まず、マイナーだが適用できない答えを切り取ります。呼び出しごとにこれらの式をほとんど使用する必要があるため、find+xargsトリックやそのバリアント(findwithなど)は使用できません。-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

見てわかるように、空白のあるパスは分割され、program2つの異なるパラメータとして扱われます。

有効日までの見積もり

私のような初心者ユーザーは、これらの問題に直面したときに最終的に動作するまでランダムに引用符を追加する傾向があるようです。ここでは役に立たないようです...

"$(…)"

$ ./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。とにかく私は「有線経路」自体で問題を引き起こさないようにfindwith-print0sortwith -を好みます。それでは、役割分割を強制してすべてを整えるのは-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

私は(上記のように)IFSbeforeと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)

おすすめ記事