在 unix shell 中生成随机文件名
我想在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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(14)
假设您使用的是 Linux,则以下内容应该有效:
如果您的系统运行时熵较低,则这只是伪随机,但(在 Linux 上)保证会终止。如果您需要真正的随机数据,请使用
/dev/random
而不是/dev/urandom
。此更改将使您的代码阻塞,直到有足够的熵可产生真正的随机输出,因此可能会减慢您的代码。对于大多数用途,/dev/urandom
的输出是足够随机的。如果您使用的是 OS X 或其他 BSD,则需要将其修改为以下内容:
Assuming you are on a linux, the following should work:
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:
为什么不使用 unix mktemp 命令:
why do not use unix mktemp command:
一条命令,无管道,无循环:
如果不需要换行符,例如在变量中使用换行符时:
使用“16”生成 32 个十六进制数字。
One command, no pipe, no loop:
If you don't need the newline, for example when you're using it in a variable:
Using "16" generates 32 hex digits.
uuidgen
正是生成此内容,只是您必须删除连字符。所以我发现这是实现这一目标的最优雅的方式(至少对我来说)。它应该可以在 Linux 和 OS X 上开箱即用。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.正如您可能从每个答案中注意到的那样,您通常必须“求助于计划”。
但是,在不使用任何外部可执行文件的情况下,在 Bash 和 ksh 中:
在 zsh 中:
将格式字符串中的小写
x
更改为大写X
使字母十六进制字符大写。这是在 Bash 中执行此操作的另一种方法,但没有显式循环:
在下面的内容中,“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:
in zsh:
Change the lower case
x
in the format string to an upper caseX
to make the alphabetic hex characters upper case.Here's another way to do it in Bash but without an explicit loop:
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 firstprintf
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 secondprintf
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 namedstring
.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.在 zsh 中测试,应该可以与任何 BASH 兼容的 shell 一起使用!
例子:
Tested in zsh, should work with any BASH compatible shell!
Example:
这个答案与 fmarks 非常相似,所以我不能真正相信它,但我发现 cat 和 tr 命令组合非常慢,而且我发现这个版本要快一些。你需要十六进制转储。
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.
您可以添加的另一件事是运行 date 命令,如下所示:
读取非秒时间,结果增加了很多随机性。
Another thing you can add is running the date command as follows:
Reads nonosecond time and the result adds a lot of randomness.
还有另一种方式[tm]。
Yet another way[tm].
第一个答案很好,但如果不需要的话为什么要分叉 cat 。
The first answer is good but why fork cat if not required.
从
/dev/random
中获取 16 个字节,将它们转换为十六进制,获取第一行,删除地址,删除空格。当然,假设“不求助于程序”意味着“仅使用现成的程序”。
Grab 16 bytes from
/dev/random
, convert them to hex, take the first line, remove the address, remove the spaces.Assuming that "without resorting to a program" means "using only programs that are readily available", of course.
如果您使用的是 Linux,那么 Python 将被预安装。因此,您可以选择类似于以下内容的内容:
如果您不喜欢破折号,请使用替换功能,如下所示
If you are on Linux, then Python will come pre-installed. So you can go for something similar to the below:
If you don't like the dashes, then use replace function as shown below
如果您的系统中有
openssl
,您可以使用它来生成具有定义长度的随机十六进制(也可以是-base64
)字符串。我发现它非常简单并且可以在 cron in one line jobs 中使用。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.希望为这个主题添加一个(也许)更好的解决方案。
注意:这仅适用于
bash4
和mktemp
的某些实现(例如 GNU 的)试试这个
这个速度是
头 /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:
另一个:
Hope to add a (maybe) better solution to this topic.
Notice: this only works with
bash4
and some implement ofmktemp
(for example, the GNU one)Try this
This one is twice as faster as
head /dev/urandom | tr -cd 'a-f0-9' | head -c 32
, and eight times as faster ascat /dev/urandom | tr -cd 'a-f0-9' | head -c 32
.Benchmark:
With mktemp:
And the other: