zsh でファイル名引数をシャッフルする

zsh でファイル名引数をシャッフルする

アプリケーションがコマンドライン引数経由でのみファイルを開くことができると仮定すると、これを実現するためにファイル名/パスのリストをランダム化するにはどうすればよいでしょうか?

これはかなり簡単なはずだと思っていましたが、どうやらスペースのせいで必要以上に複雑になっているようです。


例:

a.mp3
b.mp3
スペースあり.mp3

試してみると、$(ls | shuf)スペースはエスケープされず、次のような結果になりますwith space.mp3 b.mp3 a.mp3

引用符オプションを使用しても、-Qコマンド置換によって引用符がエスケープされ、次の結果になるため、役に立ちません。\"with space.mp3\" \"a.mp3\" \"b.mp3\"

同様に、 get のエスケープ-bもエスケープされます。with\\ space.mp3 a.mp3 b.mp3

発見事項のないfind「's」のようなものが完璧でしょう...-exec <application> {} \+

答え1

以下は、 と を削除した zsh のみのバリエーションlsですshuf

mplayer *.mp3(oe:REPLY=\$RANDOM:)

Glob 修飾子は、両方のコロン ( ) の間にあるコードoを実行します ( ) 。コードは各ファイルに疑似乱数を割り当て、結果として任意の順序になります。e:$RANDOM

コマンドをもう少しわかりにくくするために、主にキーストロークを節約するために、シェル関数を定義できますs

s() { REPLY=$RANDOM }
mplayer *.mp3(oe:s:)

CTRL+Rまたは、さらに良い方法として、シャッフル部分用のキーバインディングを定義します。

bindkey -s '^R' '(oe:REPLY=\\$RANDOM:)^M'

ここで、 のmplayer *.mp3後に のみ と入力するCTRL+Rと、 の(oe:REPLY=\$RANDOM:)部分が追加され、コマンド ラインがすぐに実行されます ( ^M)。

答え2

まったく必要ありませんls。試してみてください

mplayer "${(f)$(shuf -e *.mp3)}"

の問題はls、 のような別名が付けられることが多くls --color=always、その場合、他のプログラム (shufこの例では ) では正しく認識されない非表示の文字が出力されることです。

答え3

ようやく方法を見つけたと思います:${(f)"$(ls | shuf)"}

壊す:

ls | shuf: 期待どおりにファイル/ディレクトリをシャッフルします。
"$(...)": 引用符は、改行を含む出力をそのまま維持します。
${(f)...}: 展開の結果を改行で分割し、ファイル/ディレクトリ名の配列を生成します。


"${(f)$(ls | shuf)}"は同様に動作しますが${(f)$(ls | shuf)}、は動作しません。

関連情報