そこで、ファイル名を入力として受け取るコンソール プレーヤーで MP3 を再生したいと思います。次のファイルがあり、シェル (zsh) によって展開されますls -1 *
。*
1 - Main title.mp3
10 - End title.mp3
2 - Intro.mp3
...
しかし、明らかに、私が実際に望む順序は次のようになります。
1 - Main title.mp3
2 - Intro.mp3
...
10 - End title.mp3
それを実現するにはどのようなシェル拡張魔法が必要ですか?
巧妙なパイプを使えば同じことができることは分かっていますが、sort -h
それは実際には選択肢ではありません私は怠け者のタイピストだからしたがって、曲を追加するための小さなシェル スクリプトを作成しない限り、nyxmms2 add /path/to/dir/*.mp3
zsh の拡張機能内でフィルタリングを行う方法を検討している理由は、むしろそうしたいからです... また、ログ ファイルやリビジョンなど、他の多くの状況にも当てはまるため、これが可能かどうかを知りたいです...
答え1
使用n
グロブ修飾子。
print -lr -- *.mp3(n)
デフォルトの並び替え順序を変更するには、numeric_glob_sort
オプション。
setopt numeric_glob_sort
print -lr -- *.mp3
numeric_glob_sort
may が有効なときに 1 つのパターンに対して辞書式順序が必要な場合は、 n
glob 修飾子を否定します。
print -lr -- *(^n)
答え2
1 つの方法は、出力の表示方法を制御するために、ls
コマンドを通じて出力を実行することです。sort
人間が読める形式で並べ替える-h
(別名)を使用できます。--human-numeric-sort
$ ls | sort -h
1 - Main title.mp3
2 - Main title.mp3
10 - Main title.mp3
編集#1 - OPのコメントへの対応
上記は次のようにエイリアスにラップできます。
$ alias lss="ls | sort -h"
上記のコマンドを実行すると、次のように短縮されます。
$ lss
1 - Main title.mp3
2 - Main title.mp3
10 - Main title.mp3
参考文献
答え3
グロブの並び順は変更できますzsh
(ジルの答え) ですが、ls
引数はいずれにせよソートされ、デフォルトでは辞書順にソートされます。
ls
GNU の場合は、数値順にソートするオプションls
を使用できます。-v
ls -1v
または:
ls -1vd -- *
これは と同等ではありません。sort -h
なぜならsort -h
、 は の出力のようなものをソートするためのものでdu -h
あり、 は1.12G
より大きいからです999M
。一方ls -v
、 とzsh
の(n)
グロブ修飾子はバージョン番号のようなものをソートするように設計されています (たとえば、1.20 は 1.4 より大きい)。
これらの条件を満たすグロブが必要な場合は、そのための zsh ソート関数を記述する必要があります。
zsh では、関数を使用して glob ソート順序を定義し、それを として使用できます*(o+that-function)
。は、変数that-function
内でソートするファイル名を受け取り$REPLY
、同じ変数に返す必要があります。これにより、辞書式にソートできるようになります(も提供されているzsh
場合は数値的にもソートできます)。n
何かのようなもの:
h() {
local -A x
local match
setopt localoptions extendedglob
x=(k 1 K 1 M 2 G 3 T 4 P 5 E 6)
REPLY=${REPLY//(#b)((|[0-9]#.)[0-9]##)([${(kj::)x}])/$((match[1]*2**$x[$match[3]]0))}
}
1.1G をすべてその値 (1181116006.4) に置き換えます。
これを次のように使用できます。
ls -1Ud -- *(no+h)
(-U
GNUls
オプションはls
ない引数を並べ替える)。
1.20
ただし、小数部分のある数値の場合は、次のように並べ替えられるため、うまく機能しません1.3
。
$ ls
1.20 1.3 3.1G 500M
$ ls -v1Ud -- *(no+h)
1.3
1.20
500M
3.1G
オプションの接尾辞が付いたあらゆる種類の 10 進浮動小数点数 (-1e20M、1E-20、100k、3000M など) をソートする場合、zsh
辞書式または数値的に正の 10 進整数に制限された順序でしかソートできないため、それらを同じ順序で辞書式にソートする文字列、または同じ順序で数値的にソートする正の 10 進整数に変換する関数が必要になります。
zsh
利用可能な場合は 64 ビットの数値で浮動小数点演算と 10 進演算を行うので、それらの数値 (または少なくともzsh
浮動小数点数でサポートされている範囲) を 0 から 2 63までの整数に変換する浮動小数点関数を適用できます。対数関数を使用することもできます。次のようになります。
zmodload zsh/mathfunc
h() {
local -A x
local match v
setopt localoptions extendedglob
x=(k 1 K 1 M 2 G 3 T 4 P 5 E 6 Z 7 Y 8)
REPLY=${REPLY//(#b)([-+]|)(([0-9]#.|)[0-9]##([eE]([-+]|)[0-9]##|))\
([${(kj::)x}]|)/[$(([#10]1e15*(1500+ $match[1](745+log((v=$match[2]\
${${match[2]##*[Ee.]*}:+.}*2.**$x[$match[6]]0)==0?2.48e-324:v)))))]}
}
用途:
print -rl -- *(no+h)
または、数値ソートにフォールバックして、たとえば 1000000000000000001 と 10000000000000000002 (zsh
浮動小数点精度で同じ対数を持つ) を区別するには、次のようにします。
print -rl -- *(noe:h:on)
すると、さらに良いものが得られますsort -h
。
$ ls | sort -h
-4
-3
+20
a2
b1
b10
b2
1e-20Y
1e3
1.20
1.3
3
20
999
1000 1e9
1000 900M
1001
1024
1k
12k
0.000000001G
$ print -rl -- *(noe:h:on)
-4
-3
0.000000001G
1.20
1.3
3
20
+20
999
1e3
1000 900M
1000 1e9
1001
1k
1024
1e-20Y
12k
a2
b1
b2
b10
さて、あなたの特定のnyxmms2の問題については、Gillesの回答を補足するために、あなたが怠け者のタイピストであれば、今度は次のように定義することもできます。選択音楽ファイルに対して、(「順序付け」の代わりに) 次のような機能を使用します。
m() [[ $REPLY == (#i)*.(mp3|ogg)(-.) ]]
nyxmms2 *Zep*(n+m)
または変数を使用します:
m='.(#i)(mp3|ogg)(n-.)'
nyxmms2 *Zep*$~m
またはグローバルエイリアス:
alias -g @m='./*.(#i)(mp3|ogg)(n-.)'
nyxmms2 @m
numericglobsort のみをオンにするにはnyxmms2
、次のようにします。
preexec() {[[ $1 = nyxmms2* ]] && setopt numericglobsort}
precmd setopt nonumericglobsort
答え4
これを行うには、常にシェル拡張を使用できます。
nyxmms2 add $(ls /path/to/dir/*.mp3 | sort -n)
音楽を扱っているので、「プレイリスト」を作成するかもしれません
ls /path/to/album/or/song/*.mp3 | sort -n >> /path/to/playlist
nyxmms2 add < /path/to/playlist