【问题标题】:How to mkdir only if a directory does not already exist?仅当目录尚不存在时如何 mkdir?
【发布时间】:2010-10-22 02:04:44
【问题描述】:

我正在编写一个在 AIX 上的 KornShell (ksh) 下运行的 shell 脚本。我想使用mkdir 命令来创建一个目录。但是该目录可能已经存在,在这种情况下我不想做任何事情。所以我想测试一下目录不存在,或者抑制mkdir在尝试创建现有目录时抛出的“文件存在”错误。

我怎样才能最好地做到这一点?

【问题讨论】:

    标签: shell scripting ksh aix mkdir


    【解决方案1】:

    试试mkdir -p:

    mkdir -p foo
    

    请注意,这也会创建任何不存在的中间目录;例如,

    mkdir -p foo/bar/baz
    

    将创建目录foofoo/barfoo/bar/baz(如果它们不存在)。

    像 GNU mkdir 这样的一些实现包括 mkdir --parents 作为更易读的别名,但这在 POSIX/Single Unix 规范中没有指定,并且在许多常见平台上不可用,如 macOS、各种 BSD 和各种商业 Unix,所以应该避免。

    如果想在父目录不存在的时候报错,如果不存在想创建目录,那么可以先test判断目录是否存在:

    [ -d foo ] || mkdir foo
    

    【讨论】:

    • 您使用的缩短示例正是您不应该做的。它正在反转逻辑以节省编码空间,但它应该使用!和 && 对那些阅读它的人来说更有意义。
    • @AndreasLarsen 这个问题是关于 Unix-like 系统上的mkdir,而不是 Windows。 -p 是 POSIX/Single Unix 规范合规性所必需的,因此任何有意遵守这些规范的东西都将支持-p。 Windows 完全不同,除非您使用 POSIX 仿真层,如 Cygwin 或 MSYS。
    • 我今天发现了mkdir -p的一些有趣的东西,你可以使用括号! {} 在命令中创建“复杂”目录树。见这里:technosophos.com/2010/04/15/…
    • @MikeQ 我更喜欢|| 而不是&&,因为这样整行就有正确的退出状态。如果您的 shell 使用 errexit 运行,或者该行是函数中的最后一行、switch-case 等,则很重要。
    • @herve 这与mkdir 无关; shell 将这样的表达式扩展为传递给mkdir 的离散参数列表。
    【解决方案2】:

    使用 -p 标志。

    man mkdir
    mkdir -p foo
    

    【讨论】:

    • -p, --parents 如果存在则没有错误,根据需要制作父目录
    【解决方案3】:

    这应该可行:

    $ mkdir -p dir
    

    或:

    if [[ ! -e $dir ]]; then
        mkdir $dir
    elif [[ ! -d $dir ]]; then
        echo "$dir already exists but is not a directory" 1>&2
    fi
    

    如果目录不存在,它将创建该目录,但如果您尝试创建的目录的名称已被目录以外的其他对象使用,则会警告您。

    【讨论】:

    • 我认为 korn 中没有 -d 运算符,而是 -e 用于文件/目录,只是检查存在。此外,它们在成功时都返回 0,所以!是多余的。如果我错了,请纠正我。
    • 在这两个方面都错了,AFAIK。测试成功返回 true,并且 -d 也存在(至少在 MacOS X 上)
    • 值得一提的是,这不是线程安全的。从您检查目录是否存在到您尝试写入之间,情况可能会发生变化。
    【解决方案4】:

    或者如果你想先检查是否存在:

    if [[ ! -e /path/to/newdir ]]; then
                mkdir /path/to/newdir
    fi
    

    -eKornShell 的存在测试。

    您也可以尝试在谷歌上搜索 KornShell 手册。

    【讨论】:

      【解决方案5】:

      久经考验的老实人

      mkdir /tmp/qq >/dev/null 2>&1
      

      将在没有许多其他解决方案所具有的竞争条件的情况下做你想做的事情。

      有时最简单(也是最丑陋)的解决方案是最好的。

      【讨论】:

      • 如果“tmp”不存在,这将失败。它也没有给你任何确认。
      • 比赛条件?你能详细说明你的答案吗?非原子测试和创建?
      • @Peter,一个类似于(例如)[ -d newdir ] || mkdir newdir 的 sn-p,其中目录最初不存在,具有竞争条件,即在存在测试和尝试创建之间,另一个进程可以突然进入并创建目录。因此mkdir 会失败。
      • @Mike Q:基本路径/tmp 在示例中可能已被选择来表示始终存在并且当前用户可写入的基本路径,例如用户有足够的权限在其中创建目录。您提出了一个有效的观点::逻辑有点矛盾,因为当此命令失败时,它可能意味着两件事:1.)目录存在或 2.)目录无法创建。对于操作本身而言,情况并非如此,因此对目录路径进行简单的后检查可以给出确认,或者下一个操作的命令。
      【解决方案6】:

      用一个命令定义复杂的目录树

      mkdir -p project/{lib/ext,bin,src,doc/{html,info,pdf},demo/stat/a}
      

      【讨论】:

      • 如果存在没有错误,根据需要制作父目录
      • 请记住,这不是mkdir 本身的特性,而是执行命令的shell。它被称为大括号扩展 - AFAIK,只有 Bash、ksh、zsh 和 C shell 支持它。
      • 如果逗号周围有空格,您可能(将会)得到意想不到的结果。当心。
      • @Atlas7 声明,您需要转义通常属于正则表达式的字符。 (即,您需要使用folder\ name,而不是使用folder name
      • 这不是答案;这是一个单独的主题,更适合作为评论。
      【解决方案7】:

      mkdir foo 即使目录存在也可以工作。 要使其仅在名为“foo”的目录不存在时工作,请尝试使用-p 标志。

      例子:

      mkdir -p foo
      

      这将创建名为“foo”的目录,仅当它不存在时。 :)

      【讨论】:

      • 正如@BrianCampbell 提到的,这也会在路径中创建任何其他目录。这可能是危险的,例如卷被卸载,因为它可能会在安装点创建目录。
      【解决方案8】:

      如果您不想显示任何错误消息:

      [ -d newdir ] || mkdir newdir
      

      如果你想显示你自己的错误信息:

      [ -d newdir ] && echo "Directory Exists" || mkdir newdir
      

      【讨论】:

      • @PeterMortensen:当然。如果您不想要竞争条件,请使用mkdir -p。但是您不会显示自己的Directory exists 错误。
      【解决方案9】:
      directory_name = "foo"
      
      if [ -d $directory_name ]
      then
          echo "Directory already exists"
      else
          mkdir $directory_name
      fi
      

      【讨论】:

        【解决方案10】:

        mkdir 在 Windows 8+ 系统上不再支持 -p 开关。

        你可以用这个:

        IF NOT EXIST dir_name MKDIR dir_name
        

        【讨论】:

        • OP 是关于 AIX kornshell...与 Windows 无关,是吗?
        • 你确定以前支持过吗?你有消息来源吗?
        【解决方案11】:

        这是一个简单的函数(Bash shell),可以让您在目录不存在时创建目录。

        #------------------------------------------#
        # Create a directory if it does not exist. #
        #------------------------------------------#
        # Note the "-p" option in the mkdir        #
        # command which creates directories        #
        # recursively.                             #
        #------------------------------------------#
        createDirectory() {
           mkdir -p -- "$1"
        }
        

        您可以将上述函数调用为:

        createDirectory "$(mktemp -d dir-example.XXXXX)/fooDir/BarDir"

        如果 fooDir 和 BarDir 不存在,上面会创建它们。注意 mkdir 命令中的“-p”选项,它递归地创建目录。

        【讨论】:

          【解决方案12】:
          mkdir -p sam
          
          • mkdir = 创建目录
          • -p = --parents
          • (如果存在则没有错误,根据需要创建父目录)

          【讨论】:

            【解决方案13】:

            您可以使用if 语句来检查目录是否存在。如果不退出,则创建目录。

            1. dir=/home/dir_name

              if [ ! -d $dir ]
              then
                   mkdir $dir
              else
                   echo "Directory exists"
              fi
              
            2. 您可以使用带有 -p 选项的 mkdir 来创建目录。它会检查目录是否不可用。

              mkdir -p $dir
              

              mkdir -p 还允许创建目录的树结构。如果要使用相同的命令创建父目录和子目录,可以选择 mkdir -p

              mkdir -p /home/parent_dir /home/parent_dir/child1 /home/parent_dir/child2
              

            【讨论】:

            • 使用if循环有什么好处!?为什么有人会选择 -p 选项?!
            • 我已经分享了当文件夹不存在时创建文件夹的方法。这取决于对一个人的要求。如果您有一个用例,您需要检查文件夹是否不存在并且您想跟踪它,以便您可以使用解决方案 1。如果没关系,您可以使用解决方案 2,它将创建文件夹如果不存在。
            【解决方案14】:

            请参阅手册页 man mkdir 以获取选项 -p

               -p, --parents
                      no error if existing, make parent directories as needed
            

            它将在给定路径中创建所有目录,如果存在则不会引发错误,否则它将在给定路径中从左到右创建所有目录。试试下面的命令。在发出此命令之前,目录 newdiranotherdir 不存在

            正确用法

            mkdir -p /tmp/newdir/anotherdir

            执行命令后可以看到在/tmp下创建的newdiranotherdir。您可以根据需要多次发出此命令,该命令始终具有exit(0)。由于这个原因,大多数人在使用这些实际路径之前在 shell 脚本中使用此命令。

            【讨论】:

              【解决方案15】:
              if [ !-d $dirName ];then
                   if ! mkdir $dirName; then  # Shorter version. Shell will complain if you put braces here though
                   echo "Can't make dir: $dirName"
                   fi
              fi
              

              【讨论】:

                【解决方案16】:

                简单、沉默、致命:

                mkdir -p /my/new/dir >/dev/null 2>&1
                

                【讨论】:

                • 应该是:mkdir -p /my/new/dir >/dev/null 2>&1
                • mkdir -p my/new/dir 不会抱怨my/new/dir 已经存在,不需要重定向输出
                • 已修复错字。 Leevi,我相信我遇到了需要压制输出的情况。
                猜你喜欢
                • 1970-01-01
                • 2011-07-08
                • 2013-01-07
                • 2020-07-22
                • 1970-01-01
                • 1970-01-01
                • 2016-02-23
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多