Расширение с числами в удобном для чтения формате

Расширение с числами в удобном для чтения формате

Итак, я хочу воспроизвести несколько MP3 в консольном проигрывателе, который принимает имена файлов в качестве входных данных. У меня есть следующие файлы, как указано в ls -1 *where *get expanded моей оболочкой (zsh):

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 квалификатор glob.

print -lr -- *.mp3(n)

Вы можете изменить порядок сортировки по умолчанию, установивnumeric_glob_sortвариант.

setopt numeric_glob_sort
print -lr -- *.mp3

Если вам нужен лексикографический порядок для одного шаблона, пока numeric_glob_sortдействует may, отмените nквалификатор glob.

print -lr -- *(^n)

решение2

Одним из подходов может быть запуск вывода lsчерез команду sort, чтобы контролировать способ отображения вывода.

Вы можете использовать -h(также известный как --human-numeric-sort), который сортирует данные в удобной для восприятия форме.

$ ls | sort -h
1 - Main title.mp3
2 - Main title.mp3
10 - Main title.mp3

EDIT #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и предназначены для сортировки таких вещей, как номера версий (где 1.20 больше 1.4, например).zsh(n)

Если вам нужна подстановка, которая понимает эти достаточные значения, вам придется написать для этого функцию сортировки 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это опция GNU, lsчтобы сказатьls нетдля сортировки его аргументов).

Однако это не будет работать хорошо с числами с дробной частью, так как сортировка будет выполняться, например, 1.20после :1.3

$ ls
1.20  1.3  3.1G  500M
$ ls -v1Ud -- *(no+h)
1.3
1.20
500M
3.1G

Для чего-то, что сортировало бы все виды десятичных чисел с плавающей точкой с необязательными суффиксами (например, -1e20M, 1E-20, 100k, 3000M), поскольку zshсортировка может выполняться только лексикографически или численно, ограниченная положительными десятичными целыми числами, нам понадобится функция для преобразования их либо в строки, которые сортируются лексикографически в том же порядке, либо в положительные десятичные целые числа, которые сортируются численно в том же порядке.

zshвыполняет арифметику с плавающей точкой и десятичную арифметику с 64-битными числами, где это возможно, поэтому мы могли бы применить функцию с плавающей точкой, которая преобразует эти числа (или, по крайней мере, диапазон, поддерживаемый числами с 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 и 1000000000000000002 (которые имеют одинаковый логарифм с 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, в дополнение к ответу Жиля, если вы ленивый печатающий, вы также можете определить это время каквыбор(вместо «упорядочивания») функция для музыкальных файлов, например:

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

Связанный контент