Сгенерируйте случайное имя файла в оболочке unix
Я хотел бы создать случайное имя файла в оболочке unix (скажем, tcshell). Имя файла должно состоять из случайных 32 шестнадцатеричные цифры, например:
c7fdfc8f409c548a10a0a89a791417c5
(к которому я добавлю, что необходимо). Дело в том, что это можно сделать только в оболочке, не прибегая к программе.
12 ответов:
предполагая, что вы находитесь на linux, должно работать следующее:
cat /dev/urandom | tr -cd 'a-f0-9' | head -c 32это только псевдослучайно, если ваша система работает с низким уровнем энтропии, но (в linux) гарантированно завершится. Если вам нужны действительно случайные данные, кот
/dev/randomвместо/dev/urandom. Это изменение сделает ваш код блочным до тех пор, пока не будет доступна достаточная энтропия для получения действительно случайного вывода, поэтому он может замедлить ваш код. Для большинства применений, выход/dev/urandomдостаточно случайно.если вы в OS X или другом BSD вам нужно изменить его следующим образом:
cat /dev/urandom | env LC_CTYPE=C tr -cd 'a-f0-9' | head -c 32
почему бы не использовать команду unix mktemp:
$ TMPFILE=`mktemp tmp.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX` && echo $TMPFILE tmp.MnxEsPDsNUjrzDIiPhnWZKmlAXAO8983
одна команда, без трубы, без петли:
hexdump -n 16 -v -e '/1 "%02X"' -e '/16 "\n"' /dev/urandomЕсли вам не нужна новая строка, например, когда вы используете ее в переменной:
hexdump -n 16 -v -e '/1 "%02X"' /dev/urandomС помощью "16" генерирует 32 шестнадцатеричных цифр.
протестировано в zsh, должно работать с любой совместимой оболочкой BASH!
#!/bin/zsh SUM=`md5sum <<EOF $RANDOM EOF` FN=`echo $SUM | awk '// { print }'` echo "Your new filename: $FN"пример:
$ zsh ranhash.sh Your new filename: 2485938240bf200c26bb356bbbb0fa32 $ zsh ranhash.sh Your new filename: ad25cb21bea35eba879bf3fc12581cc9
как вы, наверное, заметили из каждого ответа, вы вообще есть чтобы "прибегнуть к программе".
однако, без использования любые внешние исполняемые файлы, в Баш и КШ:
string=''; for i in {0..31}; do string+=$(printf "%x" $(($RANDOM%16)) ); done; echo $stringв zsh:
string=''; for i in {0..31}; do string+=$(printf "%x" $(($RANDOM%16)) ); dummy=$RANDOM; done; echo $stringизменить нижний регистр
xв строке формата в верхнем регистреXчтобы сделать буквенные шестнадцатеричные символы в верхнем регистре.вот еще один способ сделать это в bash, но без явный цикл:
printf -v string '%X' $(printf '%.2s ' $((RANDOM%16))' '{00..31})в следующем, "первый" и "второй"
printfотносится к порядку, в котором они выполняются, а не к порядку, в котором они появляются в строке.этот метод использует расширение скобок для получения списка из 32 случайных чисел mod 16, за каждым из которых следует пробел и одно из чисел в диапазоне в фигурных скобках, за которым следует другое пространство (например,
11 00). Для каждого элемента этого списка, первыйprintfснимает все кроме первых двух символы, использующие его строку формата (%.2) оставляя либо одну цифру, за которой следует пробел каждая или две цифры. Пробел в строке формата гарантирует, что между каждым выходным номером будет хотя бы один пробел.подстановка команды, содержащая первый
printfне цитируется, так что разделение слов выполняется, и каждое число переходит ко второмуprintfкак отдельный аргумент. Там числа преобразуются в шестнадцатеричные с помощью%Xформат строки и они присоединяются друг к другу без пробелов (так как нет в строке формата) и результат сохраняется в переменной с именемstring., когда
printfполучает больше аргументов, чем его строка формата учитывает, формат применяется к каждому аргументу по очереди, пока все они не будут использованы. Если аргументов меньше, то несопоставимая строка формата (часть) игнорируется, но в данном случае это не применяется.я тестировал его в Bash 3.2, 4.4 и 5.0-alpha. Но это не работает в zsh (5.2) или ksh (93u+), потому что
RANDOMоценивается только один раз в расширении скобки в этих оболочках.обратите внимание, что из-за использования оператора mod на значение, которое колеблется от 0 до 32767 распределение цифр с помощью фрагментов может быть искажено (не говоря уже о том, что числа псевдо случайный в первую очередь). Однако, поскольку мы используем mod 16 и 32768 делится на 16, это не будет проблемой здесь.
в любом случае, правильный способ сделать это с помощью
mktempа в Олег Разгуляев ответ.
этот ответ очень похож на fmarks, поэтому я не могу взять на себя ответственность за это, но я нашел комбинации команд cat и tr довольно медленными, и я нашел эту версию немного быстрее. Вам необходимо вывести.
hexdump -e '/1 "%02x"' -n32 < /dev/urandom
еще один способ[tm].
R=$(echo $RANDOM $RANDOM $RANDOM $RANDOM $RANDOM | md5 | cut -c -8) FILENAME="abcdef-$R"
захватить 16 байт от
/dev/random, преобразуйте их в hex, возьмите первую строку, удалите адрес, удалите пробелы.head /dev/random -c16 | od -tx1 -w16 | head -n1 | cut -d' ' -f2- | tr -d ' 'предполагая, что "не прибегая к программе" означает "используя только программы, которые легко доступны", конечно.
Если вы находитесь на Linux, то Python будет предустановлен. Так что вы можете пойти на что-то подобное ниже:
python -c "import uuid; print str(uuid.uuid1())"Если вам не нравятся тире, то используйте функцию замены, как показано ниже
python -c "import uuid; print str(uuid.uuid1()).replace('-','')"
первый ответ хорош, но почему вилка кошка, если не требуется.
tr -dc 'a-f0-9' < /dev/urandom | head -c32
надеюсь добавить (возможно) лучшее решение этой темы.
обратите внимание: это работает только с
bash4и некоторые реализацииmktemp(например, GNU one)попробуй такое
fn=$(mktemp -u -t 'XXXXXX') echo ${fn/\/tmp\//}этот в два раза быстрее, чем
head /dev/urandom | tr -cd 'a-f0-9' | head -c 32, и в восемь раз быстрее, так какcat /dev/urandom | tr -cd 'a-f0-9' | head -c 32.тест:
С mktemp:
#!/bin/bash # a.sh for (( i = 0; i < 1000; i++ )) do fn=$(mktemp -u -t 'XXXXXX') echo ${fn/\/tmp\//} > /dev/null done time ./a.sh ./a.sh 0.36s user 1.97s system 99% cpu 2.333 totalи другие:
#!/bin/bash # b.sh for (( i = 0; i < 1000; i++ )) do cat /dev/urandom | tr -dc 'a-zA-Z0-9' | head -c 32 > /dev/null done time ./b.sh ./b.sh 0.52s user 20.61s system 113% cpu 18.653 total
еще одна вещь, которую вы можете добавить, это запуск команды date следующим образом:
date +%S%Nсчитывает несекундное время, и результат добавляет много случайности.
Comments