2010-05-08 5 views
58

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

c7fdfc8f409c548a10a0a89a791417c5 

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

+0

См. Также _ [Как создать UUID в bash?] (Https://serverfault.com/a/103366/1293) _. –

ответ

96

Предполагая, что вы находитесь на Linux, должно работать:

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

Это только псевдослучайной, если ваша система иссякает по энтропии, но is (on 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 
+3

Dang, и я думал, что у меня все хорошо :) – LukeN

+1

@ LukeN: У вас было хорошо.И технически это решение не гарантируется прекратить :) –

+1

Это решение на самом деле делало для меня странные вещи, поскольку он добавлял знак «%» с белым фоном после фактического случайного хеша, но поскольку моя оболочка обычно ведет себя странно на некоторых я не хотел, чтобы это выглядело плохо, прежде чем оно было принято :) – LukeN

5

Протестировано в 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 
+0

Я думал, что это тоже хорошо :) – fmark

+1

Это создаст только 32768 уникальных имен файлов, а не '16^32'. –

+0

Это также будет работать только в системах, содержащих двоичный файл 'md5sum'. Например, FreeBSD и OSX имеют '/ sbin/md5', которые выполняют ту же цель, но используют разные синтаксисы параметров. – ghoti

33

почему не используют Unix Mktemp команду:

$ TMPFILE=`mktemp tmp.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX` && echo $TMPFILE 
tmp.MnxEsPDsNUjrzDIiPhnWZKmlAXAO8983 
+3

В этом случае вы не только сгенерируете строку, но и создадите файл. –

+3

Некоторые реализации имеют флаг '--dry-run', чтобы предотвратить создание файла. Это, конечно, открывает возможное состояние гонки. –

1

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

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

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

+0

Я проверил это. Это намного медленнее, чем другие решения, но работает. – DJTripleThreat

+0

Да, это довольно длинная труба для чего-то простого. Я надеялся на некоторые флаги на 'od', но не мог заставить его делать то, что я хотел. fmark, хотя он обрабатывает больше байтов, на самом деле может быть быстрее. – Thomas

+0

Это было бы быстрее, если бы он использовал/dev/urandom, а не/dev/random – fmark

3

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

Тем не менее, без использования каких-либо внешних исполняемых файлов, в Bash и КШ:

for i in {0..31}; do string+=$(printf "%x" $(($RANDOM%16))); done; echo $string 

в Zsh:

for i in {0..31}; do string+=$(printf "%x" $(($RANDOM%16))); dummy=$RANDOM; done; echo $string 

Обратите внимание, что из-за использования мод оператора на значение, которое находится в диапазоне от От 0 до 32767 распределение цифр с использованием вышеприведенных фрагментов будет искажено (не говоря уже о том, что цифры pseudo случайные в первую очередь).

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

16

Одна команда, ни трубы, ни одна петля:

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

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

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

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

+0

Это потрясающе. Я никогда не думал использовать для этого 'hexdump'. – avetisk

3

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

R=$(echo $RANDOM $RANDOM $RANDOM $RANDOM $RANDOM | md5 | cut -c -8) 
FILENAME="abcdef-$R" 
+0

Программа, доступная в большинстве систем, - md5sum. Мне нравится это решение, потому что, если вам не нужна высокая случайность, вы можете просто использовать $ RANDOM только один раз, делая это самым кратчайшим наиболее читаемым решением. – nus

+0

a) Если у вас есть md5sum, вы можете заменить md5 на md5sum и соответствующим образом обновить разрез. b) Использование только одного параметра RANDOM опасно, оно отображает только значения между 0 и 32767, что очень мало, в зависимости от приложения. – reto

4

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

hexdump -e '/1 "%02x"' -n32 < /dev/urandom 
+0

Туз. Используйте '-n16' для 32 символов. – Walf

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 
0

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

date +%S%N 

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

1

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

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

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

python -c "import uuid; print str(uuid.uuid1()).replace('-','')" 
Смежные вопросы