Вы можете заключить путь в одинарные кавычки, чтобы $ не расширялся.
Использовать ключ случайной сортировки(квалификатор globoe
)::
*(Noe\''REPLY=$RANDOM,$RANDOM'\')
Пояснение:
oe
следует разделитель из одного символа -, фрагмент кода и еще один разделитель. Кусок кода не может содержать разделитель. Специальные символы необходимо экранировать, чтобы они не анализировались при анализе самих квалификаторов glob. '
в качестве символа-разделителя (с обратной косой чертой, потому что его нужно экранировать ), и я заключаю код в '
для защиты специальных символов, которые могут присутствовать. Таким образом, я могу написать произвольный код, если он не содержит '
. REPLY
изначально устанавливается на имя файла, и все, что устанавливает код REPLY
, используется в качестве ключа сортировки ). Для случайной выборки $n
элементов добавьте квалификатор […]
:
*(Noe\''REPLY=$RANDOM,$RANDOM'\'[1,$n])
Иногда некоторые элементы получают один и тот же ключ сортировки, поэтому все перестановки неравновероятны, с небольшим предпочтением сохранять любые результаты применения функции сортировки к списку в порядке каталога¹, но смещение невелико. Я использую $RANDOM,$RANDOM
в качестве ключа сортировки, а не $RANDOM
, чтобы уменьшить смещение:$RANDOM
— это 15-битное -число, и смещение будет заметно, когда количество файлов приблизится к 2^15.
Обратите внимание, что $RANDOM
достаточно хорош для выборки, если небольшое смещение не вызывает беспокойства. Он не подходит для всего, что связано с безопасностью. Если вам нужна безопасная случайная перестановка, используйте GNU coreutils shuf
. (Если в вашей любимой ОС отсутствует нативная shuf
и вы по какой-то причине не хотите устанавливать GNU coreutils, вы можете вместо этого попробовать повторную реализацию от ibara.)
securely_permuted=("${(0)$(printf '%s\0' *(N) | shuf -z))}")
или более простая версия, которая может привести к ограничению длины командной строки:
securely_permuted=("${(0)$(shuf -z -- *(N)))}")
¹ Экспериментально сорт стабилен (e.g. *(omoe\''REPLY=1'\')
эквивалентно *(om)
,но порядок только из *(oe\''REPLY=1'\')
не соответствует *(oN)
. В любом случае это небольшой перекос в пользу какого-то определенного порядка.