在 unix shell 中生成随机文件名

发布于 2024-08-31 14:30:12 字数 179 浏览 2 评论 0原文

我想在unix shell(比如tcshell)中生成一个随机文件名。文件名应由随机的 32 个十六进制字母组成,例如:(

c7fdfc8f409c548a10a0a89a791417c5

我将在其中添加必要的内容)。重点是能够仅在 shell 中完成此操作,而无需借助程序。

I would like to generate a random filename in unix shell (say tcshell). The filename should consist of random 32 hex letters, e.g.:

c7fdfc8f409c548a10a0a89a791417c5

(to which I will add whatever is neccesary). The point is being able to do it only in shell without resorting to a program.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(14

也只是曾经 2024-09-07 14:30: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

Assuming you are on a linux, the following should work:

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

This is only pseudo-random if your system runs low on entropy, but is (on linux) guaranteed to terminate. If you require genuinely random data, cat /dev/random instead of /dev/urandom. This change will make your code block until enough entropy is available to produce truly random output, so it might slow down your code. For most uses, the output of /dev/urandom is sufficiently random.

If you on OS X or another BSD, you need to modify it to the following:

cat /dev/urandom | env LC_CTYPE=C tr -cd 'a-f0-9' | head -c 32
当爱已成负担 2024-09-07 14:30:12

为什么不使用 unix mktemp 命令:

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

why do not use unix mktemp command:

$ TMPFILE=`mktemp tmp.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX` &&  echo $TMPFILE
tmp.MnxEsPDsNUjrzDIiPhnWZKmlAXAO8983
巷子口的你 2024-09-07 14:30:12

一条命令,无管道,无循环:

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

如果不需要换行符,例如在变量中使用换行符时:

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

使用“16”生成 32 个十六进制数字。

One command, no pipe, no loop:

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

If you don't need the newline, for example when you're using it in a variable:

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

Using "16" generates 32 hex digits.

笔芯 2024-09-07 14:30:12

uuidgen 正是生成此内容,只是您必须删除连字符。所以我发现这是实现这一目标的最优雅的方式(至少对我来说)。它应该可以在 Linux 和 OS X 上开箱即用。

uuidgen | tr -d '-'

uuidgen generates exactly this, except you have to remove hyphens. So I found this to be the most elegant (at least to me) way of achieving this. It should work on linux and OS X out of the box.

uuidgen | tr -d '-'
清音悠歌 2024-09-07 14:30:12

正如您可能从每个答案中注意到的那样,您通常必须“求助于计划”。

但是,在不使用任何外部可执行文件的情况下,在 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})

在下面的内容中,“first”和“second”printf 指的是它们的执行顺序,而不是它们的执行顺序。出现在行中。

该技术使用大括号扩展来生成 32 个随机数 mod 16 的列表,每个随机数后跟一个空格以及大括号中的范围内的数字之一,后跟另一个空格(例如 11 00)。对于该列表的每个元素,第一个 printf 使用其格式字符串 (%.2) 去除除前两个字符之外的所有字符,留下单个数字,每个数字后跟一个空格或两位数。格式字符串中的空格可确保每个输出数字之间至少有一个空格。

包含第一个 printf 的命令替换未加引号,以便执行分词,并且每个数字作为单独的参数发送到第二个 printf。在那里,数字通过 %X 格式字符串转换为十六进制,并且它们彼此附加,不带空格(因为格式字符串中没有空格),结果存储在变量中命名为字符串

当 printf 接收到的参数多于其格式字符串所占的参数时,该格式将依次应用于每个参数,直到它们全部被消耗为止。如果参数较少,则忽略不匹配的格式字符串(部分),但这不适用于本例。

我在 Bash 3.2、4.4 和 5.0-alpha 中测试了它。但它在 zsh (5.2) 或 ksh (93u+) 中不起作用,因为 RANDOM 在这些 shell 中的大括号扩展中仅计算一次。

请注意,由于对范围从 0 到 32767 的值使用 mod 运算符,因此使用片段的数字分布可能会出现偏差(更不用说这些数字一开始就是随机的) )。然而,由于我们使用 mod 16 并且 32768 可以被 16 整除,所以这在这里不会成为问题。

无论如何,正确的方法是使用 mktemp,如 Oleg Razgulyaev 的 答案所示。

As you probably noticed from each of the answers, you generally have to "resort to a program".

However, without using any external executables, in Bash and ksh:

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

in zsh:

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

Change the lower case x in the format string to an upper case X to make the alphabetic hex characters upper case.

Here's another way to do it in Bash but without an explicit loop:

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

In the following, "first" and "second" printf refers to the order in which they're executed rather than the order in which they appear in the line.

This technique uses brace expansion to produce a list of 32 random numbers mod 16 each followed by a space and one of the numbers in the range in braces followed by another space (e.g. 11 00). For each element of that list, the first printf strips off all but the first two characters using its format string (%.2) leaving either single digits followed by a space each or two digits. The space in the format string ensures that there is then at least one space between each output number.

The command substitution containing the first printf is not quoted so that word splitting is performed and each number goes to the second printf as a separate argument. There, the numbers are converted to hex by the %X format string and they are appended to each other without spaces (since there aren't any in the format string) and the result is stored in the variable named string.

When printf receives more arguments than its format string accounts for, the format is applied to each argument in turn until they are all consumed. If there are fewer arguments, the unmatched format string (portion) is ignored, but that doesn't apply in this case.

I tested it in Bash 3.2, 4.4 and 5.0-alpha. But it doesn't work in zsh (5.2) or ksh (93u+) because RANDOM only gets evaluated once in the brace expansion in those shells.

Note that because of using the mod operator on a value that ranges from 0 to 32767 the distribution of digits using the snippets could be skewed (not to mention the fact that the numbers are pseudo random in the first place). However, since we're using mod 16 and 32768 is divisible by 16, that won't be a problem here.

In any case, the correct way to do this is using mktemp as in Oleg Razgulyaev's answer.

泅人 2024-09-07 14:30:12

在 zsh 中测试,应该可以与任何 BASH 兼容的 shell 一起使用!

#!/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

Tested in zsh, should work with any BASH compatible shell!

#!/bin/zsh

SUM=`md5sum <<EOF
$RANDOM
EOF`

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

echo "Your new filename: $FN"

Example:

$ zsh ranhash.sh
Your new filename: 2485938240bf200c26bb356bbbb0fa32
$ zsh ranhash.sh
Your new filename: ad25cb21bea35eba879bf3fc12581cc9
昵称有卵用 2024-09-07 14:30:12

这个答案与 fmarks 非常相似,所以我不能真正相信它,但我发现 cat 和 tr 命令组合非常慢,而且我发现这个版本要快一些。你需要十六进制转储。

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

This answer is very similar to fmarks, so I cannot really take credit for it, but I found the cat and tr command combinations quite slow, and I found this version quite a bit faster. You need hexdump.

hexdump -e '/1 "%02x"' -n32 < /dev/urandom
谎言 2024-09-07 14:30:12

您可以添加的另一件事是运行 date 命令,如下所示:

date +%S%N

读取非秒时间,结果增加了很多随机性。

Another thing you can add is running the date command as follows:

date +%S%N

Reads nonosecond time and the result adds a lot of randomness.

心如狂蝶 2024-09-07 14:30:12

还有另一种方式[tm]。

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

Yet another way[tm].

R=$(echo $RANDOM $RANDOM $RANDOM $RANDOM $RANDOM | md5 | cut -c -8)
FILENAME="abcdef-$R"
ζ澈沫 2024-09-07 14:30:12

第一个答案很好,但如果不需要的话为什么要分叉 cat 。

tr -dc 'a-f0-9' < /dev/urandom | head -c32

The first answer is good but why fork cat if not required.

tr -dc 'a-f0-9' < /dev/urandom | head -c32
顾冷 2024-09-07 14:30:12

/dev/random 中获取 16 个字节,将它们转换为十六进制,获取第一行,删除地址,删除空格。

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

当然,假设“不求助于程序”意味着“仅使用现成的程序”。

Grab 16 bytes from /dev/random, convert them to hex, take the first line, remove the address, remove the spaces.

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

Assuming that "without resorting to a program" means "using only programs that are readily available", of course.

同尘 2024-09-07 14:30:12

如果您使用的是 Linux,那么 Python 将被预安装。因此,您可以选择类似于以下内容的内容:

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

如果您不喜欢破折号,请使用替换功能,如下所示

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

If you are on Linux, then Python will come pre-installed. So you can go for something similar to the below:

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

If you don't like the dashes, then use replace function as shown below

python -c "import uuid; print str(uuid.uuid1()).replace('-','')"
暖阳 2024-09-07 14:30:12

如果您的系统中有openssl,您可以使用它来生成具有定义长度的随机十六进制(也可以是-base64)字符串。我发现它非常简单并且可以在 cron in one line jobs 中使用。

 openssl rand -hex 32
 8c5a7515837d7f0b19e7e6fa4c448400e70ffec88ecd811a3dce3272947cb452

If you have openssl in your system you can use it for generating random hex (also it can be -base64) strings with defined length. I found it pretty simple and usable in cron in one line jobs.

 openssl rand -hex 32
 8c5a7515837d7f0b19e7e6fa4c448400e70ffec88ecd811a3dce3272947cb452
表情可笑 2024-09-07 14:30:12

希望为这个主题添加一个(也许)更好的解决方案。

注意:这仅适用于 bash4mktemp 的某些实现(例如 GNU 的)

试试这个

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

这个速度是头 /dev/urandom | tr -cd 'a-f0-9' | tr -cd 'a-f0-9' | head -c 32,速度是 cat /dev/urandom | 的八倍tr -cd 'a-f0-9' | tr -cd 'a-f0-9' |头-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

Hope to add a (maybe) better solution to this topic.

Notice: this only works with bash4 and some implement of mktemp(for example, the GNU one)

Try this

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

This one is twice as faster as head /dev/urandom | tr -cd 'a-f0-9' | head -c 32, and eight times as faster as cat /dev/urandom | tr -cd 'a-f0-9' | head -c 32.

Benchmark:

With 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

And the other:

#!/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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文