83

UNIXシェル(たとえばtcshell)でランダムなファイル名を生成したいと思います。ファイル名は、ランダムな32文字の16進文字で構成する必要があります。例:

c7fdfc8f409c548a10a0a89a791417c5

(必要なものは何でも追加します)。重要なのは、プログラムに頼ることなく、シェルでのみそれを実行できることです。

4

14 に答える 14

132

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
于 2010-05-08T11:22:39.237 に答える
45

unixmktempコマンドを使用しない理由:

$ TMPFILE=`mktemp tmp.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX` &&  echo $TMPFILE
tmp.MnxEsPDsNUjrzDIiPhnWZKmlAXAO8983
于 2010-05-08T11:28:20.970 に答える
21

1つのコマンド、パイプなし、ループなし:

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

改行が不要な場合、たとえば変数で使用している場合:

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

「16」を使用すると、32桁の16進数が生成されます。

于 2012-05-30T20:25:16.247 に答える
7

それぞれの答えからおそらくお気づきかもしれませんが、通常「プログラムに頼る」必要があります。

ただし、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して、アルファベットの16進文字を大文字にします。

Bashでそれを行う別の方法がありますが、明示的なループはありません。

printf -v string '%X' $(printf '%.2s ' $((RANDOM%16))' '{00..31})

以下において、「第1」および「第2」printfは、それらが行に現れる順序ではなく、それらが実行される順序を指す。

この手法では、中かっこ展開を使用して、32個の乱数mod 16のリストを作成します。各乱数の後にスペースが続き、中かっこ内の範囲内の数値の1つに別のスペースが続きます(例11 00)。そのリストの各要素について、printf最初の文字はフォーマット文字列(%.2)を使用して最初の2文字を除くすべてを取り除き、1桁の数字の後にスペースまたは2桁の数字を残します。フォーマット文字列のスペースは、各出力番号の間に少なくとも1つのスペースがあることを保証します。

最初のコマンドを含むコマンド置換printfは引用符で囲まれていないため、単語の分割が実行され、各数値はprintf個別の引数として2番目の数値になります。そこで、数値は%Xフォーマット文字列によって16進数に変換され、スペースなしで互いに追加され(フォーマット文字列には何もないため)、結果はという名前の変数に格納されますstring

フォーマット文字列が説明するprintfよりも多くの引数を受け取ると、すべてが消費されるまで、フォーマットが各引数に順番に適用されます。引数が少ない場合、一致しないフォーマット文字列(部分)は無視されますが、この場合は適用されません。

Bash 3.2、4.4、5.0-alphaでテストしました。ただし、zsh(5.2)またはksh(93u +)ではRANDOM、これらのシェルのブレース展開で一度だけ評価されるため、機能しません。

0から32767の範囲の値でmod演算子を使用するため、スニペットを使用した数字の分布が歪む可能性があることに注意してください(最初から数値が疑似ランダムであるという事実は言うまでもありません)。ただし、mod 16を使用しており、32768は16で割り切れるので、ここでは問題になりません。

いずれにせよ、これを行う正しい方法は、OlegRazgulyaevの回答のmktempように使用することです。

于 2010-05-08T12:49:55.427 に答える
6

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
于 2010-05-08T11:15:07.407 に答える
6

uuidgenハイフンを削除する必要がある場合を除いて、これを正確に生成します。だから私はこれがこれを達成するための最もエレガントな(少なくとも私にとっては)方法であることに気づきました。箱から出してすぐにLinuxとOSXで動作するはずです。

uuidgen | tr -d '-'
于 2019-08-16T14:35:59.587 に答える
4

さらに別の方法[tm]。

R=$(echo $RANDOM $RANDOM $RANDOM $RANDOM $RANDOM | md5 | cut -c -8)
FILENAME="abcdef-$R"
于 2013-05-31T15:48:52.710 に答える
3

この答えはfmarksに非常に似ているので、私はそれを信用することはできませんが、catコマンドとtrコマンドの組み合わせが非常に遅く、このバージョンはかなり速いことがわかりました。hexdumpが必要です。

hexdump -e '/1 "%02x"' -n32 < /dev/urandom
于 2014-07-21T19:49:42.233 に答える
3

最初の答えは良いですが、必要がないのになぜ猫をフォークするのですか。

tr -dc 'a-f0-9' < /dev/urandom | head -c32
于 2018-04-13T23:27:54.383 に答える
2

から16バイトを/dev/random取得し、それらを16進数に変換し、最初の行を取得し、アドレスを削除し、スペースを削除します。

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

もちろん、「プログラムに頼らずに」とは、「すぐに利用できるプログラムのみを使用する」ことを意味します。

于 2010-05-08T11:28:55.853 に答える
2

追加できるもう1つのことは、次のようにdateコマンドを実行することです。

date +%S%N

ナノ秒以外の時間を読み取り、その結果は多くのランダム性を追加します。

于 2016-07-11T22:52:00.760 に答える
1

このトピックに(多分)より良い解決策を追加したいと思っています。

注意:これは、 (たとえば、GNUのもの)のbash4一部の実装でのみ機能しますmktemp

これを試して

fn=$(mktemp -u -t 'XXXXXX')
echo ${fn/\/tmp\//}

これは、の2倍head /dev/urandom | tr -cd 'a-f0-9' | head -c 32、8倍の速度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
于 2015-06-09T15:43:51.140 に答える
1

Linuxを使用している場合は、Pythonがプリインストールされています。したがって、以下のようなものを探すことができます。

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

ダッシュが気に入らない場合は、以下に示すように置換機能を使用してください

python -c "import uuid; print str(uuid.uuid1()).replace('-','')"
于 2016-08-11T22:13:20.220 に答える
1

システムにある場合は、これを使用して、定義された長さopensslのランダムな16進(場合もあります)文字列を生成できます。-base64私はそれが非常にシンプルで、cronの1行のジョブで使用できることを発見しました。

 openssl rand -hex 32
 8c5a7515837d7f0b19e7e6fa4c448400e70ffec88ecd811a3dce3272947cb452
于 2019-01-02T15:15:20.390 に答える