Python中的mkdir -p功能

时间:2009-03-01 18:49:39

标签: python mkdir

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

12 个答案:

答案 0 :(得分:965)

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.makedirsoptional third argument exist_ok,如果为true,则启用mkdir -p功能 - 除非 {{1提供并且现有目录具有与预期目录不同的权限;在这种情况下,mode会像之前一样被提升。

更新2

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

OSError

在Python 3.5中添加了import pathlib pathlib.Path("/tmp/path/to/desired/directory").mkdir(parents=True, exist_ok=True) 参数。

答案 1 :(得分:236)

在Python> = 3.2中,那是

os.makedirs(path, exist_ok=True)

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

答案 2 :(得分:150)

这比捕获异常更容易:

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

免责声明此方法需要两个系统调用,在某些环境/条件下更容易受到竞争条件的影响。如果您正在编写比在受控环境中运行的简单一次性脚本更复杂的东西,那么最好使用只需要一次系统调用的已接受答案。

更新2012-07-27

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

答案 3 :(得分:47)

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

In [17]: from distutils.dir_util import mkpath

In [18]: mkpath('./foo/bar')
Out[18]: ['foo', 'foo/bar']

答案 4 :(得分:18)

如果文件已存在,

mkdir -p会出错:

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

如果raise返回os.path.isdir(检查False时),对以前建议的改进将重新errno.EEXIST例外。

(更新)另见highly similar question;我同意接受的答案(和警告),但我建议使用os.path.isdir代替os.path.exists

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

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

答案 5 :(得分:14)

正如其他解决方案中所提到的,我们希望能够在模仿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失败的文件,但现在一个目录就在其位置。这并不重要,因为在最后一个文件系统调用目录时,该函数只会在不引发异常的情况下以静默方式退出。

答案 6 :(得分:14)

来自python3标准库的Pathlib

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

如果父母是真的,那么这条道路的任何失踪父母都被创建为   需要;它们是使用默认权限创建的,无需考虑   考虑模式(模仿POSIX mkdir -p命令)。   如果exist_ok为false(默认值),则会引发FileExistsError   目标目录已存在。

     

如果exist_ok为true,则将忽略FileExistsError异常(相同   行为如POSIX mkdir -p命令),但仅限于最后一个路径   component不是现有的非目录文件。

     

在版本3.5中更改:已添加exist_ok参数。

答案 7 :(得分:12)

我认为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

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

答案 8 :(得分:7)

功能声明;

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))

答案 9 :(得分:4)

我个人已经取得了以下成功,但我的功能应该被称为“确保此目录存在':

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

答案 10 :(得分:3)

import os
import tempfile

path = tempfile.mktemp(dir=path)
os.makedirs(path)
os.rmdir(path)

答案 11 :(得分:2)

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的答案,但修复了部分树已存在的错误