【问题标题】:How do I create 100 files with 1 random number in each of them and give them permissions based on the number如何创建 100 个文件,每个文件都有 1 个随机数,并根据数字授予它们权限
【发布时间】:2022-01-18 20:29:00
【问题描述】:

我需要创建一个 bash 脚本来创建 100 个包含随机数的文件。 我尝试使用:

for i in {1..100}; do $RANDOM > RANDOM.txt

我不知道这样做是否正确。 然后我需要根据文件内的数字给文件读写和执行权限。不知道该怎么做。 我尝试使用:

if [ $i%2==0 ]
then
echo chmod +rw $RANDOM.txt

但这似乎不起作用

刚收到一些反馈,结果证明我做错了一切。 我必须创建 100 个文件 1.txt 到 100.txt 我使用 touch {1..100}.txt 然后在每个文件中粘贴 1 个随机数。我应该使用 echo 还是 shuf 来执行此操作?

【问题讨论】:

  • 文件也应该有随机名称吗?名字和里面的随机数一样吗?
  • 你在正确的轨道上。首先创建一个 bash 脚本。创建一个从 1 到 10 的循环并打印该数字。一旦成功,在该循环中,使用类似 echo $NUM > ${NUM}.txt 的方式将数字写入文件。一旦你有这个工作,添加 $NUM % 2 或任何你喜欢的 if 逻辑。 chmod 644 ${NUM}.txt 如果满足 if 逻辑,否则 chmod 640 ${NUM}.txt。一旦可行,您所要做的就是找到一种从静态数字变为随机数字的方法。你可以使用stackoverflow.com/questions/2556190/…

标签: bash shell


【解决方案1】:

首先,您需要回显随机数,而不是将其用作命令。

其次,如果要使用与文件名和内容相同的随机数,则需要将其保存到变量中。否则你每次写$RANDOM都会得到不同的数字。

第三,这不是你在[] 中做算术和条件的方式,任何shell 脚本教程都应该显示正确的方法。您还可以使用带有 (( expression )) 的 bash 算术表达式。

#!/bin/bash
for i in {1..100}
do
    r=$RANDOM
    echo "$r" > "$r.txt"
    if (( i % 2 == 0 ))
    then
        chmod +rw "$r.txt"
    fi
done

【讨论】:

  • 我可以在使用这个模型时使用多个条件吗? #!/bin/bash rm -r -f *.txt for i in {1..100} do r=$RANDOM echo "$r" > "$r.txt" if (( i % 2 == 0 ) ) 然后 chmod +rw "$r.txt" elif (( i % 3 == 0 )) 然后 chmod +rwx "$r.txt" else chmod -r "$r.txt" fi 完成
  • 当然,你为什么会这么想呢?
【解决方案2】:

我认为使用具有八进制权限的chmod 是最简单的,例如0777 用于rwxrwxrwx 等。

例子:

#!/bin/bash

for((i=0; i<100; ++i)) {
    rnd=$RANDOM                     # pick a random number
    (( perm = rnd % 512 ))          # make it in the range [0, 512) (0000-0777 oct)
    printf -v octperm "%04o" $perm  # convert to octal

    file=$rnd.txt                   # not sure if you meant to name it after the number
    echo $rnd > $file

    chmod $octperm $file            # chmod with octal number
}

文件摘录:

-r-xrw--wx 1 ted users   5 15 dec 17.53 6515.txt
---x-wxrwx 1 ted users   5 15 dec 17.53 6751.txt
-rwx-w--w- 1 ted users   5 15 dec 17.53 8146.txt
-rw-r----- 1 ted users   5 15 dec 17.53 8608.txt
--w--w---x 1 ted users   5 15 dec 17.53 8849.txt
--wx----wx 1 ted users   5 15 dec 17.53 8899.txt
--wxrwx-wx 1 ted users   5 15 dec 17.53 8955.txt
-rw-r-xrw- 1 ted users   5 15 dec 17.53 9134.txt
...

如果您想考虑您当前的umask,您也可以这样做,方法是屏蔽umask 指示的权限中的位。

#!/bin/bash

(( um = ~$(umask) ))  # bitwise negated umask

for((i=0; i<100; ++i)) {
    rnd=$RANDOM

    (( perm = (rnd % 01000) & um ))    # [0000,0777] bitwise AND umask
    printf -v octperm "%04o" $perm

    file=$i.$rnd.txt                   # using $i. to make name unique
    echo $rnd > $file

    chmod $octperm $file
}

如果您的 umask 当前为 0022,则上述示例不会为 group 和/或 others 创建任何可写文件,而其他(正常)权限将随机。

【讨论】:

  • 避免无用的分叉!使用:printf -v octperm "%04o" "$perm"
  • @F.Hauri 哦,我不认为那会分叉。我会在一小时内检查一下。感谢您的提示!
  • @F.Hauri 我刚试了一下,你的建议快了 43%。非常感谢!
  • @M.NejatAydin 绝对是的。我记下了代码中的命名。我不确定OP真正想要什么。要获得唯一的名称,可以在名称中的某处插入$i.。我将其添加到第二个示例中以显示如何完成。
【解决方案3】:

使用awk,您可以尝试关注一次。该程序还负责关闭后端打开的文件(以防我们收到错误“打开的文件太多”一次)。用 GNU awk 编写和测试。

awk -v numberOfFiles="100" '
BEGIN{
  srand()
  for(i=1;i<=numberOfFiles;i++){
    out=(int(1 + rand() * 10000))
    print out > (out".txt")
    system("chmod +rw " out".txt")
    close(out)
  }
}'

我创建了一个名为numberOfFilesawk 变量,其中我给出了100(根据需要创建100 个文件),您也可以根据需要保留它,以后如果需要更改它我们不需要在此处更改其余程序中的任何内容。

【讨论】:

    【解决方案4】:

    来自Ted Lyngmo's answer

    使用一些bashisms,例如使用整数变量属性避免分叉...

    declare -i um=" ~$(umask) " i rnd perm
    for((i=100;i--;)){
         rnd=RANDOM
         perm=' ( rnd % 01000 ) & um '
         printf -v file file-%03d-%04X.txt $i $rnd
         printf -v octperm "%04o" "$perm"
         echo "$rnd" > "$file"
         chmod "$octperm" "$file"
    }
    

    (文件名是用十进制的文件号和十六进制的随机数构建的)

    关于演出

    可能会快一点,因为避免了分叉和使用整数。

    (这里使用的for((;;)){ ;}语法并不快,只是不同(更短)...
    事实上,for ((i=100;i--;)) ;do ...;done (不知不觉地)比for i in {1..100};do ...;done 慢!我只是想将这种不寻常的语法用于 extreme bashism... ;)

    一些比较:

    export TIMEFORMAT=$'(%U + %S) / \e[1m%R\e[0m : %P'
    

    关于 forks,尝试 1'000 变量赋值进行格式化,使用 printf

    time for i in {1..1000};do var=$(printf "foo");done 
    (0.773 + 0.347) / 1.058 : 105.93
    
    time for i in {1..1000};do printf -v var "foo";done 
    (0.006 + 0.000) / 0.006 : 99.80
    

    在我的主机上从 1.5 秒到 6 毫秒!!!没有讨论:forks(语法$(printf...))要避免!!

    关于整数属性(使用 100'000 次二元运算):

    declare -i intvar
    
    time for i in {1..100000};do var=$(( ( 431214 % 01000 ) & -19 ));done
    (0.272 + 0.005) / 0.278 : 99.46  
    
    time for i in {1..100000};do intvar=' ( 431214 % 01000 ) & -19 ';done 
    (0.209 + 0.000) / 0.209 : 99.87  
    

    从 0.28 秒到 0.21 秒,这不太重要,但是。

    关于 for i in {for ((i=(现在使用 1'000'000 个循环):

    time for i in {1..1000000};do :;done
    (1.600 + 0.000) / 1.602 : 99.86
    
    time for ((i=1000000;i--;));do :;done
    (1.880 + 0.001) / 1.882 : 99.95
    

    但这显然不太重要(关心内存消耗,使用大括号)。

    【讨论】:

    • 这比我当前的版本快几个百分点。好的! ...但如果我更改为for i in {1..100};do,它实际上与我的版本的速度差不多。
    • 我运行了大量测试,在我的机器上循环到 10000,for i in {1..10000} 循环一直比for((i=0; i&lt;10000; ++i)) { 版本慢。可能是版本不同。我在测试中使用了“GNU bash,版本 5.1.0(1)-release (x86_64-redhat-linux-gnu)”。
    • 新增性能对比,看看
    • 嗯,我无法解释差异。我为整个脚本计时,使用两个不同的循环创建了 10000 个文件(唯一的区别是循环)。一致的结果。如果我将脚本缩小到一个循环,只打印$i 的值(并将脚本输出传送到/dev/null),结果与您显示的完全一样。很有趣。
    猜你喜欢
    • 2022-10-16
    • 1970-01-01
    • 2016-06-19
    • 1970-01-01
    • 2016-03-23
    • 2015-05-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多