Program Tip

Python의 mkdir -p 기능

programtip 2020. 9. 29. 18:26
반응형

Python의 mkdir -p 기능 [중복]


이 질문에 이미 답변이 있습니다.

mkdir -pPython 내에서 셸 과 유사한 기능을 얻는 방법이 있습니까? 시스템 호출 이외의 솔루션을 찾고 있습니다. 코드가 20 줄 미만이라고 확신하고 누군가 이미 작성했는지 궁금합니다.


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의 경우, true 인 경우 기능을 활성화 os.makedirs하는 선택적 세 번째 인수 가 있습니다.이 옵션 이 제공 되지 않고 기존 디렉토리가 의도 한 것과 다른 권한을 갖지 않는 한 ; 이 경우 이전과 같이 발생합니다.exist_okmkdir -p modeOSError

업데이트 2

Python ≥ 3.5의 경우 다음도 있습니다 pathlib.Path.mkdir.

import pathlib

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

exist_ok매개 변수는 파이썬 3.5에서 추가되었다.


Python> = 3.2에서는

os.makedirs(path, exist_ok=True)

이전 버전에서는 @tzot의 대답을 사용하십시오 .


이것은 예외를 트래핑하는 것보다 쉽습니다.

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

면책 조항 이 접근 방식에는 특정 환경 / 조건에서 경쟁 조건에 더 취약한 두 개의 시스템 호출이 필요합니다. 제어 된 환경에서 실행되는 간단한 일회용 스크립트보다 더 정교한 것을 작성하는 경우 하나의 시스템 호출 만 필요로하는 수용된 답변을 사용하는 것이 좋습니다.

업데이트 2012-07-27

이 답변을 삭제하고 싶지만 아래 댓글 스레드에 가치가 있다고 생각합니다. 따라서 위키로 변환하고 있습니다.


최근에 distutils.dir_util.mkpath를 찾았습니다 .

In [17]: from distutils.dir_util import mkpath

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

mkdir -p gives you an error if the file already exists:

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

So a refinement to the previous suggestions would be to re-raise the exception if os.path.isdir returns False (when checking for errno.EEXIST).

(Update) See also this highly similar question; I agree with the accepted answer (and caveats) except I would recommend os.path.isdir instead of os.path.exists.

(Update) Per a suggestion in the comments, the full function would look like:

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

As mentioned in the other solutions, we want to be able to hit the file system once while mimicking the behaviour of mkdir -p. I don't think that this is possible to do, but we should get as close as possible.

Code first, explanation later:

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

As the comments to @tzot's answer indicate there are problems with checking whether you can create a directory before you actually create it: you can't tell whether someone has changed the file system in the meantime. That also fits in with Python's style of asking for forgiveness, not permission.

So the first thing we should do is try to make the directory, then if it goes wrong, work out why.

As Jacob Gabrielson points out, one of the cases we must look for is the case where a file already exists where we are trying to put the directory.

With mkdir -p:

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

The analogous behaviour in Python would be to raise an exception.

So we have to work out if this was the case. Unfortunately, we can't. We get the same error message back from makedirs whether a directory exists (good) or a file exists preventing the creation of the directory (bad).

The only way to work out what happened is to inspect the file system again to see if there is a directory there. If there is, then return silently, otherwise raise the exception.

The only problem is that the file system may be in a different state now than when makedirs was called. eg: a file existed causing makedirs to fail, but now a directory is in its place. That doesn't really matter that much, because the the function will only exit silently without raising an exception when at the time of the last file system call the directory existed.


With Pathlib from python3 standard library:

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

If parents is true, any missing parents of this path are created as needed; they are created with the default permissions without taking mode into account (mimicking the POSIX mkdir -p command). If exist_ok is false (the default), an FileExistsError is raised if the target directory already exists.

If exist_ok is true, FileExistsError exceptions will be ignored (same behavior as the POSIX mkdir -p command), but only if the last path component is not an existing non-directory file.

Changed in version 3.5: The exist_ok parameter was added.


I think Asa's answer is essentially correct, but you could extend it a little to act more like mkdir -p, either:

import os

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

or

import os
import errno

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

These both handle the case where the path already exists silently but let other errors bubble up.


Function declaration;

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

usage :

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

I've had success with the following personally, but my function should probably be called something like 'ensure this directory exists':

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

import os
import tempfile

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

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)

based on @Dave C's answer but with a bug fixed where part of the tree already exists

참고URL : https://stackoverflow.com/questions/600268/mkdir-p-functionality-in-python

반응형