Генерация случайного имени файла в оболочке Unix

Я хотел бы создать случайное имя файла в оболочке Unix (скажем, tcshell). Имя файла должно состоять из случайных 32 шестнадцатеричных букв, например:

c7fdfc8f409c548a10a0a89a791417c5

(к которому я добавлю все необходимое). Дело в том, что это можно сделать только в оболочке, не прибегая к программе.

66 голосов | спросил R S 8 Maypm10 2010, 15:06:46

13 ответов


0

Если вы работаете в Linux, должно работать следующее:

cat /dev/urandom | tr -cd 'a-f0-9' | head -c 32

Это псевдослучайный случай, если в вашей системе заканчивается энтропия, но (в Linux) она гарантированно завершится. Если вам нужны действительно случайные данные, cat /dev/random вместо /dev/urandom. Это изменение будет блокировать ваш код до тех пор, пока энтропия не станет достаточной для создания действительно случайного вывода, что может замедлить ваш код. Для большинства случаев вывод /dev/urandom достаточно случайный.

Если вы используете OS X или другой BSD, вам нужно изменить его следующим образом:

cat /dev/urandom | env LC_CTYPE=C tr -cd 'a-f0-9' | head -c 32
ответил fmark 8 Maypm10 2010, 15:22:39
0

почему не используйте команду unix mktemp:

$ TMPFILE=`mktemp tmp.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX` &&  echo $TMPFILE
tmp.MnxEsPDsNUjrzDIiPhnWZKmlAXAO8983
ответил Oleg Razgulyaev 8 Maypm10 2010, 15:28:20
0

Одна команда, без канала, без цикла:

hexdump -n 16 -v -e '/1 "%02X"' -e '/16 "\n"' /dev/urandom

Если вам не нужна новая строка, например, когда вы используете ее в переменной:

hexdump -n 16 -v -e '/1 "%02X"' /dev/urandom

Использование "16" генерирует 32 шестнадцатеричные цифры.

ответил Dennis Williamson 31 Mayam12 2012, 00:25:16
0

Протестировано в zsh, должно работать с любой BASH-совместимой оболочкой!

#!/bin/zsh

SUM=`md5sum <<EOF
$RANDOM
EOF`

FN=`echo $SUM | awk '// { print $1 }'`

echo "Your new filename: $FN"

Пример:

$ zsh ranhash.sh
Your new filename: 2485938240bf200c26bb356bbbb0fa32
$ zsh ranhash.sh
Your new filename: ad25cb21bea35eba879bf3fc12581cc9
ответил LukeN 8 Maypm10 2010, 15:15:07
0

Как вы, наверное, заметили из каждого ответа, у вас обычно есть "прибегнуть к программе".

Однако без использования каких-либо внешних исполняемых файлов в Bash и ksh:

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

В любом случае, правильный способ сделать это - использовать mktemp, как в ответе Олега Разгуляева .

ответил Dennis Williamson 8 Maypm10 2010, 16:49:55
0

Этот ответ очень похож на fmarks, поэтому я не могу поверить ему, но я нашел комбинации команд cat и tr довольно медленными, и я обнаружил, что эта версия немного быстрее. Вам нужен hexdump.

hexdump -e '/1 "%02x"' -n32 < /dev/urandom
ответил srclosson 21 J000000Monday14 2014, 23:49:42
0

Еще один способ [тм].

R=$(echo $RANDOM $RANDOM $RANDOM $RANDOM $RANDOM | md5 | cut -c -8)
FILENAME="abcdef-$R"
ответил reto 31 Maypm13 2013, 19:48:52
0

Первый ответ хорош, но зачем разветвляться, если не требуется.

tr -dc 'a-f0-9' < /dev/urandom | head -c32
ответил Josiah DeWitt 14 AMpSat, 14 Apr 2018 02:27:54 +030027Saturday 2018, 02:27:54
0

Извлеките 16 байтов из /dev/random, преобразуйте их в шестнадцатеричные, возьмите первую строку, удалите адрес, удалите пробелы.

head /dev/random -c16 | od -tx1 -w16 | head -n1 | cut -d' ' -f2- | tr -d ' '

Предполагая, что «не прибегая к программе», разумеется, означает «использовать только легкодоступные программы».

ответил Thomas 8 Maypm10 2010, 15:28:55
0

Надеюсь добавить (возможно) лучшее решение для этой темы.

Обратите внимание: это работает только с bash4 и некоторыми реализациями mktemp (например, GNU)

Попробуйте это

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

Benchmark:

С помощью 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
ответил 罗泽轩 9 J0000006Europe/Moscow 2015, 18:43:51
0

Если вы работаете в Linux, Python предустановится. Таким образом, вы можете пойти на что-то похожее на следующее:

python -c "import uuid; print str(uuid.uuid1())"

Если вам не нравятся тире, используйте функцию замены, как показано ниже

python -c "import uuid; print str(uuid.uuid1()).replace('-','')"
ответил Thyag 12 AM00000010000002031 2016, 01:13:20
0

Еще одна вещь, которую вы можете добавить, это выполнить команду date следующим образом:

date +%S%N

Читает вне времени, и результат добавляет много случайности.

ответил user3174711 12 J000000Tuesday16 2016, 01:52:00
0

Если у вас есть openssl в вашей системе, вы можете использовать его для генерации случайного гекса (также это может быть -base64) строки определенной длины. Я нашел это довольно простым и удобным в работе cron в одной строке.

 openssl rand -hex 32
 8c5a7515837d7f0b19e7e6fa4c448400e70ffec88ecd811a3dce3272947cb452
ответил Alex 2 Jpm1000000pmWed, 02 Jan 2019 18:15:20 +030019 2019, 18:15:20

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132