【问题标题】:Creating directories with increasing name using mkdir [duplicate]使用 mkdir 创建名称递增的目录 [重复]
【发布时间】:2023-12-17 20:35:01
【问题描述】:

我想要一个 bash 脚本来创建名为“exam_folder”的文件夹,如果该文件夹已经存在(例如,我会再次运行该脚本),该脚本将创建“exam_folder_1”并且该文件夹是否存在我希望脚本创建“exam_folder_2”等等。我想聪明地拥有它:) 我得到了这样的东西:

function create_folder {

if [ -d "$1" ]; then # if exists
    mkdir $1_`i_max` # function i_max would find out the max number and add 1
else 
    mkdir $1
fi }

感谢您的帮助。

【问题讨论】:

标签: bash shell directory


【解决方案1】:

你可以这样做:

max=`ls -1d exam_folder* | tr -dc '[0-9\n]' | sort -k 1,1n | tail -1`
mkdir exam_folder_$((max + 1))

请注意,如果您同意,它不会填补序列中的“漏洞”。

【讨论】:

    【解决方案2】:

    这应该可以在任何符合 POSIX 的 shell 下工作(尽管我不能 100% 确定 [ "$foo" -eq "$foo" ] is-number-check)。我在dashbusybox' ash 下对其进行了快速测试。

    create_folder()
    {
        if [ -e "$1" ]; then
            i=0
            for d in "$1"_*; do
                _i="${d##*_}"
                [ "${_i}" -eq "${_i}" ] 2>/dev/null && i="${_i}"
            done
            i=$((i+1))
            mkdir "$1_${i}"
        else
            mkdir "$1"
        fi
    }
    

    【讨论】:

      【解决方案3】:

      两个ansers:兼容的和纯的

      最后编辑:使正则表达式更精确,并更正了一些计数错误。

      类似:

      create_folder() {
          if [ -e "$1" ] ;then
              counter=1;
              while [ -e "$1-$counter" ] ;do 
                  counter=$((counter+1))
                  done
              mkdir "$1-$counter";
          else
              mkdir "$1";
          fi;
      }
      

      可以:

      $ ls -ltr /tmp |grep foo
      $ create_folder /tmp/foo\ bar
      $ create_folder /tmp/foo\ bar
      $ create_folder /tmp/foo\ bar
      $ ls -ltr /tmp |grep foo
      drwxr-xr-x  2 user user   4096  1 mai 10:53 foo bar
      drwxr-xr-x  2 user user   4096  1 mai 10:53 foo bar-1
      drwxr-xr-x  2 user user   4096  1 mai 10:53 foo bar-2
      

      或者使用更好的格式和另一种计数方式(如果存在许多目录则更快,因为它使用专门的计数功能,但如果存在分叉则更长。):

      create_folder() {
          if [ -e "$1" ] ;then
              counter=`/bin/ls -1 "$1" "$1-"* 2>&1 | grep -E "^$1(-[0-9]*)?" | wc -l`;
              nname="`printf "%s-%04d" "$1" $counter`";
              mkdir "$nname";
          else
              mkdir "$1";
          fi;
      }
      

      这是在不同的 实现下测试的:

      $ create_folder /tmp/test
      $ ls -ltr /tmp/| grep test
      drwxr-xr-x 2 user user 4096 Apr 30 13:25 test
      
      $ create_folder /tmp/test
      $ create_folder /tmp/test
      $ ls -ltr /tmp/| grep test
      drwxr-xr-x 2 user user 4096 Apr 30 13:25 test
      drwxr-xr-x 2 user user 4096 Apr 30 13:26 test-0001
      drwxr-xr-x 2 user user 4096 Apr 30 13:26 test-0002
      

      并且目录名包含空格:

      $ create_folder "foo bar"
      $ create_folder "foo bar"
      $ create_folder "foo bar"
      $ create_folder "foo bar"
      $ ls -ltr | grep foo
      drwxr-xr-x 2 user user 4096 Apr 30 13:35 foo bar
      drwxr-xr-x 2 user user 4096 Apr 30 13:35 foo bar-0001
      drwxr-xr-x 2 user user 4096 Apr 30 13:35 foo bar-0002
      drwxr-xr-x 2 user user 4096 Apr 30 13:35 foo bar-0003
      

      对于 的粉丝:

      create_folder() {
          local -a list
          local counter nname
          if [ -e "$1" ] ;then
              list=("$1-"*)
              list=(${list[@]// /_})
              list=(${list[@]//*\*})
              counter=$((${#list[@]}+1))
              printf -v nname "%s-%04d" "$1" $counter
              mkdir "$nname";
          else
              mkdir "$1";
          fi;
      }
      

      非常快,没有分叉和漂亮的格式:

      $ create_folder "/tmp/foo bar"
      $ create_folder "/tmp/foo bar"
      $ create_folder "/tmp/foo bar"
      $ create_folder "/tmp/foo bar"
      
      $ ls -ltr /tmp/ | tail -n 4
      drwxr-xr-x  2 user user 4096  1 mai 11:17 foo bar
      drwxr-xr-x  2 user user 4096  1 mai 11:17 foo bar-0001
      drwxr-xr-x  2 user user 4096  1 mai 11:17 foo bar-0002
      drwxr-xr-x  2 user user 4096  1 mai 11:17 foo bar-0003
      

      【讨论】:

      • 诺诺,don't parse the output of ls。除此之外,尝试运行create_folder "foo bar" 两三遍,看看你的代码还有什么问题。
      • @AdrianFrühwirth 好的,我错过了一个双引号:printf "%s-%04d" "$1"。与 pure bash 相比,它的主要优点是也可以在 busybox 下工作。
      • @AdrianFrühwirth 因为在lswc -l 之间有一个grep,所以不解析ls 输出 在这里无关紧要,但还是谢谢。
      • 确实如此,而且它在busybox下以某种方式工作是编写不必要的丑陋代码的糟糕借口。此外,由于您只计算行数,因此如果有像 foo barquux 这样的文件夹,它会考虑这些并不必要地跳过这些索引(不是错误的行为,但不是用户可能期望的)。
      • @AdrianFrühwirth 我不确定我的代码是否比您的代码难看(我发现使用变量名,如 counternnamedi 更具可读性;-)。不管有没有分叉,它都可以工作并保持兼容。