在unix shell中生成随机文件名

R S*_*R S 72 unix random shell tcsh

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

c7fdfc8f409c548a10a0a89a791417c5
Run Code Online (Sandbox Code Playgroud)

(我将添加任何必要的内容).关键是能够在shell中完成它而不需要求助于程序.

fma*_*ark 118

假设你在Linux上,以下应该工作:

cat /dev/urandom | tr -cd 'a-f0-9' | head -c 32
Run Code Online (Sandbox Code Playgroud)

如果你的系统在熵上运行不足,这只是伪随机的,但是(在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
Run Code Online (Sandbox Code Playgroud)

  • 我认为这里的问题是BSD和Mac将字符串解释为多字节而不是单字节.我没有机器试试这个,所以如果这样可以报告回来:cat/dev/urandom | env LC_CTYPE = C tr -cd'a-f0-9'| 头-c 32 (4认同)
  • 看起来像另一个无用的猫:-) (2认同)

Ole*_*aev 41

为什么不使用unix mktemp命令:

$ TMPFILE=`mktemp tmp.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX` &&  echo $TMPFILE
tmp.MnxEsPDsNUjrzDIiPhnWZKmlAXAO8983
Run Code Online (Sandbox Code Playgroud)

  • 在这种情况下,您不仅会生成字符串,还会创建一个文件. (5认同)
  • 某些实现具有`--dry-run`标志以防止创建文件.那当然会打开一个可能的竞争条件. (5认同)

Pau*_*ce. 20

一个命令,没有管道,没有循环:

hexdump -n 16 -v -e '/1 "%02X"' -e '/16 "\n"' /dev/urandom
Run Code Online (Sandbox Code Playgroud)

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

hexdump -n 16 -v -e '/1 "%02X"' /dev/urandom
Run Code Online (Sandbox Code Playgroud)

使用"16"生成32个十六进制数字.


Pau*_*ce. 7

正如您可能从每个答案中注意到的那样,您通常必须 "诉诸程序".

但是,在Bash和ksh中不使用任何外部可执行文件:

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

在zsh中:

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

x将格式字符串中的小写更改为大写,X以使字母十六进制字符为大写.

这是在Bash中执行此操作的另一种方法,但没有显式循环:

printf -v string '%X' $(printf '%.2s ' $((RANDOM%16))' '{00..31})
Run Code Online (Sandbox Code Playgroud)

在下文中,"第一"和"第二" printf指的是它们被执行的顺序而不是它们在该行中出现的顺序.

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

printf不引用包含第一个的命令替换,以便执行分词,并且每个数字printf作为单独的参数进入第二个.在那里,数字由%X格式字符串转换为十六进制,并且它们彼此附加而没有空格(因为格式字符串中没有任何内容),结果存储在名为的变量中string.

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

我在Bash 3.2,4.4和5.0-alpha中测试了它.但它在zsh(5.2)或ksh(93u +)中不起作用,因为RANDOM只在这些shell的大括号扩展中得到一次评估.

请注意,由于在0到32767范围内使用mod运算符,使用片段的数字分布可能会有所偏差(更不用说数字首先是随机的这一事实).但是,由于我们使用的是mod 16和32768可以被16整除,所以这里不会有问题.

在任何情况下,要做到这一点正确的方法是使用mktemp奥列格Razgulyaev的答案.


Luk*_*keN 5

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

#!/bin/zsh

SUM=`md5sum <<EOF
$RANDOM
EOF`

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

echo "Your new filename: $FN"
Run Code Online (Sandbox Code Playgroud)

例:

$ zsh ranhash.sh
Your new filename: 2485938240bf200c26bb356bbbb0fa32
$ zsh ranhash.sh
Your new filename: ad25cb21bea35eba879bf3fc12581cc9
Run Code Online (Sandbox Code Playgroud)


小智 5

uuidgen生成正是这个,除非你必须删除连字符。所以我发现这是实现这一目标的最优雅(至少对我而言)的方式。它应该在 linux 和 OS X 上开箱即用。

uuidgen | tr -d '-'
Run Code Online (Sandbox Code Playgroud)