首页 文章

Python中的mkdir -p功能[复制]

提问于
浏览
645

这个问题在这里已有答案:

有没有办法从Python中获取类似于shell上的 mkdir -p 的功能 . 我正在寻找除系统调用之外的解决方案 . 我确信代码少于20行,我想知道是否有人写过它?

12 回答

  • 139

    mkdir -p 功能如下:

    import errno    
    import os
    
    
    def mkdir_p(path):
        try:
            os.makedirs(path)
        except OSError as exc:  # Python >2.5
            if exc.errno == errno.EEXIST and os.path.isdir(path):
                pass
            else:
                raise
    

    更新

    对于Python≥3.2, os.makedirs 有一个optional third argument exist_ok ,当为true时,启用 mkdir -p 功能 - 不提供 mode 并且现有目录具有与预期目录不同的权限;在这种情况下, OSError 如前所述 .

    更新2

    对于Python≥3.5,还有pathlib.Path.mkdir

    import pathlib
    
    pathlib.Path("/tmp/path/to/desired/directory").mkdir(parents=True, exist_ok=True)
    

    在Python 3.5中添加了 exist_ok 参数 .

  • 199

    最近,我发现了这个distutils.dir_util.mkpath

    In [17]: from distutils.dir_util import mkpath
    
    In [18]: mkpath('./foo/bar')
    Out[18]: ['foo', 'foo/bar']
    
  • 11

    正如其他解决方案中所提到的,我们希望能够在模仿 mkdir -p 的行为时命中文件系统一次 . 我不认为这是可能的,但我们应该尽可能接近 .

    代码优先,稍后说明:

    import os
    import errno
    
    def mkdir_p(path):
        """ 'mkdir -p' in Python """
        try:
            os.makedirs(path)
        except OSError as exc:  # Python >2.5
            if exc.errno == errno.EEXIST and os.path.isdir(path):
                pass
            else:
                raise
    

    由于对@ tzot的回答的注释表明在实际创建目录之前检查是否可以创建目录存在问题:在此期间您无法判断是否有人更改了文件系统 . 这也符合Python要求宽恕的风格,而不是许可 .

    所以我们要做的第一件事就是尝试制作目录,然后如果出错,找出原因 .

    正如Jacob Gabrielson指出的那样,我们必须寻找的一个案例是我们试图放置目录的文件已存在的情况 .

    使用 mkdir -p

    $ touch /tmp/foo
    $ mkdir -p /tmp/foo
    mkdir: cannot create directory '/tmp/foo': File exists
    

    Python中的类似行为是引发异常 .

    因此,如果是这种情况,我们必须解决 . 不幸的是,我们做不到 . 我们从makedirs获得相同的错误消息,无论目录是否存在(正常)还是存在防止创建目录(坏)的文件 .

    解决问题的唯一方法是再次检查文件系统以查看是否有目录 . 如果有,则以静默方式返回,否则引发异常 .

    唯一的问题是文件系统现在可能处于与调用makedirs时不同的状态 . 例如:存在导致makedirs失败的文件,但现在有一个目录 . 这并不重要,因为在最后一个文件系统调用目录时,该函数只会在不引发异常的情况下静默退出 .

  • 42

    我认为Asa的答案基本上是正确的,但您可以将其扩展一点,以便更像 mkdir -p ,或者:

    import os
    
    def mkdir_path(path):
        if not os.access(path, os.F_OK):
            os.mkdirs(path)
    

    要么

    import os
    import errno
    
    def mkdir_path(path):
        try:
            os.mkdirs(path)
        except os.error, e:
            if e.errno != errno.EEXIST:
                raise
    

    这两个都处理路径已经静默存在的情况,但让其他错误冒出来 .

  • 5

    我个人已经取得了成功,但我的函数应该被称为“确保此目录存在”:

    def mkdirRecursive(dirpath):
        import os
        if os.path.isdir(dirpath): return
    
        h,t = os.path.split(dirpath) # head/tail
        if not os.path.isdir(h):
            mkdirRecursive(h)
    
        os.mkdir(join(h,t))
    # end mkdirRecursive
    
  • 2

    在Python> = 3.2中,那就是

    os.makedirs(path, exist_ok=True)
    

    在早期版本中,请使用@tzot's answer .

  • 10
    import os
    import tempfile
    
    path = tempfile.mktemp(dir=path)
    os.makedirs(path)
    os.rmdir(path)
    
  • 16
    import os
    from os.path import join as join_paths
    
    def mk_dir_recursive(dir_path):
    
        if os.path.isdir(dir_path):
            return
        h, t = os.path.split(dir_path)  # head/tail
        if not os.path.isdir(h):
            mk_dir_recursive(h)
    
        new_path = join_paths(h, t)
        if not os.path.isdir(new_path):
            os.mkdir(new_path)
    

    基于@Dave C的答案,但修复了部分树已存在的错误

  • 0

    如果文件已存在,则 mkdir -p 会出错:

    $ touch /tmp/foo
    $ mkdir -p /tmp/foo
    mkdir: cannot create directory `/tmp/foo': File exists
    

    因此,如果 os.path.isdir 返回 False (检查 errno.EEXIST 时),对先前建议的改进将是重新 raise 异常 .

    (更新)另见highly similar question;我同意接受的答案(和警告),除了我建议 os.path.isdir 而不是 os.path.exists .

    (更新)根据评论中的建议,完整功能如下所示:

    import os
    def mkdirp(directory):
        if not os.path.isdir(directory):
            os.makedirs(directory)
    
  • 2

    功能声明;

    import os
    def mkdir_p(filename):
    
        try:
            folder=os.path.dirname(filename)  
            if not os.path.exists(folder):  
                os.makedirs(folder)
            return True
        except:
            return False
    

    用法:

    filename = "./download/80c16ee665c8/upload/backup/mysql/2014-12-22/adclient_sql_2014-12-22-13-38.sql.gz"
    
    if (mkdir_p(filename):
        print "Created dir :%s" % (os.path.dirname(filename))
    
  • 907

    这比捕获异常更容易:

    import os
    if not os.path.exists(...):
        os.makedirs(...)
    

    Disclaimer 这种方法需要两个系统调用,在某些环境/条件下更容易受到竞争条件的影响 . 如果你最好接受只需要一个系统调用的接受答案 .

    UPDATE 2012-07-27

    我很想删除这个答案,但我认为下面的评论帖中有 Value . 因此,我将其转换为维基 .

  • 10

    使用python3标准库中的Pathlib

    Path(mypath).mkdir(parents=True, exist_ok=True)
    

    如果父母是真的,那么根据需要创建这条路径的任何失踪父母;它们是使用默认权限创建的,不考虑模式(模仿POSIX mkdir -p命令) . 如果exist_ok为false(默认值),则在目标目录已存在的情况下引发FileExistsError . 如果exist_ok为true,则将忽略FileExistsError异常(与POSIX mkdir -p命令相同的行为),但前提是最后一个路径组件不是现有的非目录文件 . 在版本3.5中更改:添加了exist_ok参数 .

相关问题