Это еще более поздний ответ на поздний ответ @ gniourf_gniourf, за который я только что проголосовал, потому что это, безусловно, лучший ответ, дважды. (Один раз для избежания eval
и один раз для безопасной обработки имени файла.)
Но мне потребовалось несколько минут, чтобы распутать "не очень хорошо документированные" функции, которые использует этот ответ. Если ваши навыки Bash достаточно сильны, чтобы вы сразу увидели, как это работает, пропустите этот комментарий. Но я этого не сделал, и, распутав это, думаю, это стоит объяснить.
Feature # 1 - это глобальное копирование файла оболочки. a=(*)
создает массив $a
, членами которого являются файлы в текущем каталоге. Bash понимает все странности имен файлов, поэтому список гарантированно корректен, гарантированно экранирован и т. Д. Не нужно беспокоиться о правильном разборе текстовых имен файлов, возвращаемых ls
.
Функция # 2 - это Bash Расширения параметров для массивов , одна вложена в другую. Это начинается с ${#ARRAY[@]}
, который увеличивается до длины $ARRAY
.
Это расширение затем используется для индексации массива. Стандартный способ найти случайное число от 1 до N состоит в том, чтобы взять значение случайного числа по модулю N. Нам нужно случайное число от 0 до длины нашего массива. Вот подход, разбитый на две строки для ясности:
LENGTH=${#ARRAY[@]}
RANDOM=${a[RANDOM%$LENGTH]}
Но это решение делает это в одной строке, удаляя ненужное присвоение переменной.
Feature # 3 is Расширение Bash Brace , хотя я должен признаться, я не совсем понимаю это. Расширение скобок используется, например, для создания списка из 25 файлов с именами filename1.txt
, filename2.txt
и т. Д .: echo "filename"{1..25}".txt"
.
Выражение внутри подоболочки выше, "${a[RANDOM%${#a[@]}]"{1..42}"}"
, использует этот трюк для создания 42 отдельных расширений. Расширение фигурных скобок помещает одну цифру между ]
и }
, которые сначала я думал, что подписывает массив, но если это так, ему предшествует двоеточие. (Он также возвратил бы 42 последовательных элемента из случайного места в массиве, что совсем не то же самое, что вернуть 42 случайных элемента из массива.) Я думаю, что это просто заставляет оболочку запускать расширение 42 раза, возвращая тем самым 42 случайных предмета из массива. (Но если кто-то сможет объяснить это более полно, я бы хотел услышать это.)
Причина, по которой N должен быть жестко задан (до 42), заключается в том, что расширение фигурной скобки происходит до расширения переменной.
Наконец, вот Feature # 4 , если вы хотите сделать это рекурсивно для иерархии каталогов:
shopt -s globstar
a=( ** )
Включает параметр оболочки , который приводит к рекурсивному совпадению **
. Теперь ваш массив $a
содержит каждый файл во всей иерархии.