各サブフォルダから任意のファイルを選択してください。

各サブフォルダから任意のファイルを選択してください。

このトピックに受け入れられる答えからインスピレーションを得ました。ディレクトリ内の任意のファイルXを一覧表示現在のディレクトリの各サブフォルダからファイルを選択するために2行を合わせようとしましたが、成功しませんでした。

rand() REPLY=$RANDOM
for x in *; do y=$($x/*(o+rand[1])); print ${y:r}; done

y拡張機能が正しく機能していないようです。なぜ?

上記のコードにはどのような問題がありますか?

ベストアンサー1

問題はの拡張ではなく、yそれに割り当てられた値です。y

あなたはこれを持っています

y=$($x/*(o+rand[1]))

割り当てられた値はコマンド置換()の結果です$(…)。代替コマンドの唯一の「単語」はglob式です。これは、選択したファイルをコマンドとして実行しようとすることを意味します(これによりエラーが発生し、有用な出力が生成されない可能性があります)。

機能するには(変更された意味にもかかわらず)、コマンドの代替割り当てを配列割り当てに変更できます(例:次の削除$=

y=($x/*(o+rand[1]))

コマンド置換を維持するには、コマンドとして実行するのではなく、選択したパス名を出力する必要があります。

y=$(print -- $x/*(o+rand[1]))

しかし、ここには隠された問題があります。各globは別々のサブシェルで評価されるため、各ディレクトリは同じ乱数シーケンスを使用して項目をソートします。各ディレクトリに対して、REPLYに割り当てられた値の順序を使用して確認すると、set -xこれを確認できます。これは、ファイルがディレクトリ全体で独立して選択されないことを意味します。

以下は、パラメータにグローバル拡張を割り当てるために使用できるいくつかの選択肢です(これらの計算は$RANDOM同じシェルで維持されるため、選択は(より独立しています)):

for y in $x/*(o+rand[1]); do print -- ${y:r}; done
set -- $x/*(o+rand[1]); print -l -- ${@:r}

空のディレクトリを処理するには、おそらくNglob修飾子を追加する必要があります(NULL_GLOB設定と同様)。これは、外部globと一致するディレクトリではない場合にも役立ちます(/glob修飾子を使用してディレクトリに限定することはできますが)。

rand() REPLY=$RANDOM
for x in *(/); do y=($x/*(No+rand[1])); print -l -- ${y:r}; done

おすすめ記事