Python

Pythonでフォルダ作成する方法|mkdir・makedirs・Path.mkdirの違いと「なければ作成」

Pythonでフォルダ作成する方法|mkdir・makedirs・Path.mkdirの違いと「なければ作成」

Pythonでフォルダ(ディレクトリ)を作るなら、標準ライブラリだけで済みます。途中の階層ごと作り、すでにあってもエラーにしない書き方は次の1行です。

from pathlib import Path

Path("output/2026/11").mkdir(parents=True, exist_ok=True)

osモジュールならos.makedirs("output/2026/11", exist_ok=True)が同じ動きをします。この記事では、os.mkdir・os.makedirs・Path.mkdirの違い、「フォルダがなければ作成」を安全に書く方法、作成時のエラーの読み方、一括作成、アクセス権の指定までを、Python 3.12.13・3.14.6・3.15.0で実行した結果とあわせて説明します。

まとめ

  • 新規コードはPath(p).mkdir(parents=True, exist_ok=True)かos.makedirs(p, exist_ok=True)を使う。os.mkdirは1階層しか作れない
  • 「なければ作成」はexists()で確かめてから作るのではなく、exist_ok=Trueに任せる。8プロセス同時実行の検証では、確認してから作る書き方が200回中193回でFileExistsErrorになった
  • exist_ok=Trueでも、同名のファイルがある場合はFileExistsError、途中にファイルがある場合はNotADirectoryErrorになる
  • 保存先をos.makedirs(os.path.dirname(path))で作ると、ファイル名だけのパスで空文字になりFileNotFoundErrorになる。Path(path).parent.mkdir(...)なら起きない
  • modeは末端のフォルダにだけ効く(3.7以降)。途中の階層まで指定したいときはPython 3.15で追加されたparent_modeを使う
  • pathlibは3.4以降の標準ライブラリで、pip install pathlibは不要

フォルダを作る3つの書き方と使い分け

フォルダ作成の関数は3つあります。違いは「途中の階層を作れるか」と「既存のときにエラーを止められるか」です。

書き方 途中の階層 既存のとき 戻り値
os.mkdir(p) 作らない(FileNotFoundError) FileExistsError None
os.makedirs(p, exist_ok=True) 作る 何もしない None
Path(p).mkdir(parents=True, exist_ok=True) 作る 何もしない None

どれも戻り値はNoneです。d = Path("out").mkdir()と書くとdはNoneになるので、パスは先に変数へ入れてからmkdirを呼びます。

1階層だけ作るos.mkdir

os.mkdirは指定した1つのフォルダだけを作ります。親フォルダが無ければFileNotFoundError、同じ名前のフォルダがあればFileExistsErrorです。親が必ずあり、既存なら異常として止めたい場面(作業ごとに新しいフォルダを作る処理など)に向きます。

import os

os.mkdir("reports")            # 作成される

for path in ["reports", "logs/2026"]:
    try:
        os.mkdir(path)
    except (FileExistsError, FileNotFoundError) as e:
        print(type(e).__name__, e)
# FileExistsError [Errno 17] File exists: 'reports'
# FileNotFoundError [Errno 2] No such file or directory: 'logs/2026'(logsが無い場合)

深い階層までまとめて作るos.makedirsとPath.mkdir

途中の階層も含めて作るのがos.makedirsとPath.mkdir(parents=True)です。シェルのmkdir -pに相当します。os.makedirsの公式ドキュメントによると、exist_ok引数はPython 3.2で、Path.mkdirのexist_okは3.5で追加されました。

import os
from pathlib import Path

os.makedirs("data/raw/2026", exist_ok=True)

out = Path("data") / "processed" / "2026"
out.mkdir(parents=True, exist_ok=True)
(out / "result.csv").write_text("id,value\n", encoding="utf-8")

どちらを選ぶかは、周りのコードに合わせれば十分です。パスをPathで持ち回している、あるいは作ったフォルダの中にすぐファイルを書くならPath.mkdirのほうが続けて書けます。文字列のパスを扱う既存コードならos.makedirsで問題ありません。

フォルダがなければ作成する書き方

「フォルダが無いときだけ作る」は、exist_ok=Trueを付けるだけで書けます。存在確認のifは要りません。

from pathlib import Path

Path("output").mkdir(parents=True, exist_ok=True)   # 無ければ作る・あれば何もしない

exists()で確かめてから作る書き方を避ける理由

次のような「確認してから作る」書き方は、確認と作成のあいだに別の処理が同じフォルダを作るとFileExistsErrorで落ちます。複数のプロセスやスレッドが同じ出力先を使うバッチで起きる問題です。

import os

if not os.path.exists("out"):   # ここで「無い」と判定しても
    os.mkdir("out")             # この間に別プロセスが作るとFileExistsError

macOS(論理CPU 16)・Python 3.14.6で、8プロセスが同時にこの書き方で同じフォルダを作る試行を200回繰り返したところ、193回の試行でFileExistsErrorが出ました(合計382件)。同じ条件でos.makedirs("out", exist_ok=True)に替えると、エラーは0件でした。exist_ok=Trueは作成を試み、失敗したときにそのパスがフォルダかどうかを確かめて、フォルダなら例外を出さずに終わります。そのため、同じフォルダを並行して作ったときのFileExistsErrorは防げます(処理全体が不可分になるわけではないので、作った直後に別プロセスが削除する場合までは防げません)。

exist_ok=Trueでもエラーになる2つのケース

exist_ok=Trueが黙るのは、そのパスにフォルダがある場合だけです。Path.mkdirの公式ドキュメントにも、パスがフォルダ以外として存在する場合はFileExistsErrorを送出すると書かれています。

from pathlib import Path

Path("report").write_text("x")   # 同じ名前のファイルを置く

for target in [Path("report"), Path("report") / "2026"]:
    try:
        target.mkdir(parents=True, exist_ok=True)
    except (FileExistsError, NotADirectoryError) as e:
        print(type(e).__name__, e.errno)
# FileExistsError 17
# NotADirectoryError 20

出力先と同じ名前の拡張子なしファイル(reportなど)が残っていると、この2つが出ます。エラーが出たら、そのパスにあるのがファイルかどうかを確認してください。

フォルダがあるか確認する方法

作成とは別に、フォルダの有無だけを知りたい場合はis_dir()を使います。exists()はファイルでもTrueを返すため、「フォルダがあるか」の判定には向きません。

from pathlib import Path
import os

p = Path("output")
p.is_dir()          # フォルダならTrue(ファイルやパスが無い場合はFalse)
p.exists()          # ファイルでもフォルダでもTrue
os.path.isdir("output")   # os.pathでの同じ判定

前の章のとおり、「無ければ作る」目的なら確認は不要です。is_dir()は、フォルダが無いときに処理を止めて利用者へ知らせる場面(入力フォルダの指定ミスの検出など)で使います。

フォルダ作成で起きるエラーと対処

例外の種類ごとの原因

例外 主な原因 対処
FileExistsError 既存フォルダ/同名ファイル exist_ok=True/同名ファイルを確認
FileNotFoundError 親フォルダが無い parents=True/makedirs
FileNotFoundError パスが空文字 Path(path).parentを使う
NotADirectoryError 途中の階層がファイル そのファイルを移すか別名にする
PermissionError 親フォルダに書き込み権限が無い 出力先を変える/権限を確認

PermissionErrorは、親フォルダの権限を555(書き込み不可)にした状態でos.mkdirを呼ぶと再現します。一方、権限を555にしたフォルダそのものにos.makedirs(..., exist_ok=True)を呼んだ場合は、すでにフォルダがあるのでエラーになりませんでした。

os.path.dirnameの空文字によるFileNotFoundError

「保存するファイルの親フォルダを作る」処理をos.path.dirnameで書くと、ファイル名だけのパスを渡されたときに失敗します。os.path.dirname("out.csv")は空文字''を返し、os.makedirs('')はFileNotFoundErrorになるためです。

import os
from pathlib import Path

save_path = "out.csv"
try:
    os.makedirs(os.path.dirname(save_path), exist_ok=True)
except FileNotFoundError as e:
    print(e)   # [Errno 2] No such file or directory: ''

Path(save_path).parent.mkdir(parents=True, exist_ok=True)   # parentはPath('.')なので成功

Path("out.csv").parentはカレントフォルダを表すPath('.')になるので、この問題は起きません。保存先がコマンドライン引数などで変わる処理では、Path(...).parent.mkdir(parents=True, exist_ok=True)の形にしておくのが安全です。

Windowsで作れないフォルダ名と260文字の制限

macOSやLinuxで動いたコードが、Windowsではフォルダ名のせいで失敗することがあります。Microsoftのファイル名の規則では、次の文字と名前が使えません。

  • 文字:< > : " / \ | ? *と、制御文字(コード1〜31)
  • 名前:CON・PRN・AUX・NUL・COM1〜COM9・LPT1〜LPT9など(NUL.txtのように拡張子を付けても同じ扱い)
  • 末尾の空白とピリオドは避ける(ファイルシステムは受け付けても、エクスプローラーなどで扱えない)

たとえば時刻入りのフォルダ名を"12:30"のように作ると、macOSでは作成できてもWindowsでは失敗します。日時はstrftime("%Y%m%d_%H%M%S")のようにコロンを含まない形式にしてください。パスの長さは、通常のWin32パスでは260文字(MAX_PATH)が上限です。Windows 10 バージョン1607以降は、管理者がグループポリシー「Win32の長いパスを有効にする」かレジストリのLongPathsEnabledを有効にすると、Pythonの公式ドキュメントのとおりosモジュールなどで260文字を超えるパスを扱えます。ただし、同じフォルダを開く他のアプリケーションが長いパスに対応しているとは限りません。利用者の入力をフォルダ名に使う場合は、..で上の階層へ抜ける入力にも注意が要ります(ディレクトリトラバーサルとは?攻撃の仕組みと正規化後検証による実装対策を解説)。

modeとumaskによるアクセス権の指定

LinuxやmacOSでは、mode引数で作るフォルダのアクセス権を指定できます。指定した値のうち、プロセスのumaskで立っているビットは外されます(mode & ~umask)。umaskが022なら、既定の0o777は0o755、0o700は0o700のままです。

注意したいのは、modeが末端のフォルダにだけ効く点です。os.makedirsはPython 3.7から途中の階層にmodeを適用しなくなり、Path.mkdir(parents=True)も途中の階層は既定の権限で作ります。umask 022で実行した結果は次のとおりでした(3.12.13・3.14.6・3.15.0で同じ)。

from pathlib import Path
import os

Path("p1/p2/leaf").mkdir(mode=0o700, parents=True)
# p1=0o755  p1/p2=0o755  p1/p2/leaf=0o700

os.makedirs("m1/m2/leaf", mode=0o700)
# m1=0o755  m1/m2=0o755  m1/m2/leaf=0o700

途中の階層も他のユーザーから見えないようにしたい場合、Python 3.14までは、公式ドキュメントが示すようにmakedirsの前にumaskを変える(os.umask(0o077)など)か、階層ごとにos.mkdir(p, 0o700)を呼ぶ方法があります。umaskはプロセス全体の設定なので、変えた場合は作成後に元の値へ戻してください。2026年10月9日リリースのPython 3.15では、os.makedirsとPath.mkdirにparent_mode引数が追加され、途中の階層の権限を直接指定できます。

# Python 3.15以降
from pathlib import Path
import os

Path("a/b/c").mkdir(mode=0o700, parents=True, parent_mode=0o700)
# a=0o700  a/b=0o700  a/b/c=0o700

os.makedirs("x/y/z", mode=0o750, parent_mode=0o700)
# x=0o700  x/y=0o700  x/y/z=0o750

Python 3.14.6でparent_modeを渡すとTypeError: Path.mkdir() got an unexpected keyword argument 'parent_mode'になります。3.14以前でも動かす必要があるコードでは使わないでください。なお、Windowsではmodeはほぼ無視され、Python 3.12.4以降では0o700だけが「作成したユーザーと管理者だけがアクセスできる」設定として扱われます(CVE-2024-4030の対策)。

名前リスト・日付による複数フォルダの一括作成

決まった構成のフォルダをまとめて作るときは、名前のリストをループで回します。exist_ok=Trueを付けておけば、何度実行しても同じ結果になります。

from pathlib import Path

base = Path("project_2026")
for name in ["input", "output", "logs", "docs/spec", "docs/minutes"]:
    (base / name).mkdir(parents=True, exist_ok=True)

日付ごとのフォルダはstrftimeで階層を作ると、年・月・日で並べ替えやすくなります。

from datetime import date
from pathlib import Path

day_dir = Path("logs") / date.today().strftime("%Y/%m/%d")   # logs/2026/11/01
day_dir.mkdir(parents=True, exist_ok=True)

フォルダ名をCSVやExcelの一覧から読み込む場合は、前の章のWindowsで使えない文字が混ざっていないかを作成前に確かめてください。もう1つ、パスの途中に..を含めないことも大切です。os.makedirs("q/../w/e")を実行すると、目的のw/eに加えてqという空のフォルダも作られました。公式ドキュメントにも、作る要素に..が含まれるとmakedirsは混乱すると注記されています。

こうした出力フォルダの準備は、帳票出力やファイル連携を含む業務処理の一部として組み込むことが多い処理です。社内の定型業務をスクリプトから業務システムへ移す場合は、フルスクラッチ開発として要件から設計できます。

作成したフォルダへのファイル作成と上書き防止

フォルダを作った直後にファイルを置く処理は、目的によって書き方が変わります。

from pathlib import Path

out = Path("output")
out.mkdir(parents=True, exist_ok=True)

(out / "empty.txt").touch()                                   # 空ファイル(あればアクセス日時と更新日時を更新)
(out / "memo.txt").write_text("作成済み\n", encoding="utf-8")   # 中身を書く(あれば上書き)

with open(out / "once.txt", "x", encoding="utf-8") as f:       # 既存ならFileExistsError
    f.write("初回だけ書く\n")

touch()は既定でexist_ok=Trueのため、ファイルがあればFileExistsErrorにはならず、アクセス日時と更新日時が現在時刻になります(権限が無い場合などはPermissionErrorになります)。上書きを防ぎたいときはopen(..., "x")かtouch(exist_ok=False)を使います。なおwrite_textは親フォルダを作らないので、フォルダが無ければFileNotFoundErrorです。

tempfileによる一時フォルダの作成と後片付け

処理の途中でだけ使う作業フォルダは、自分で名前を決めてmkdirするよりtempfileに任せるほうが安全です。名前が衝突せず、作成したユーザーだけが読み書きできる権限(手元の実行では0o700)で作られます。

import tempfile
from pathlib import Path

with tempfile.TemporaryDirectory(prefix="job_") as tmp:
    work = Path(tmp)
    (work / "part.csv").write_text("a,b\n", encoding="utf-8")
# withを抜けると中身ごと削除される

keep = tempfile.mkdtemp()   # 自動では消えない。不要になったらshutil.rmtree(keep)

フォルダ名と現在の作業フォルダの取得

作ったフォルダの名前だけを取り出すにはname、現在の作業フォルダはPath.cwd()で取得します。

from pathlib import Path

Path("data/2026").name    # '2026'
Path.cwd()                # 現在の作業フォルダ(絶対パス)

作業フォルダは「スクリプトを置いた場所」ではなく、プロセスの現在の作業フォルダです。通常は起動した場所ですが、IDEの実行設定やos.chdir()で変わります。スクリプトと同じ場所にフォルダを作りたい場合は、Path(__file__).resolve().parentを基準にします。resolve()の有無で何が変わるかはPath(__file__).resolve().parentとは|Python pathlibのresolve()・absolute()の違いとBASE_DIRの書き方で詳しく扱っています。

pathlibはpip install不要

pathlibはPython 3.4から標準ライブラリに入っているので、インストールせずにfrom pathlib import Pathで使えます。PyPIにあるpathlibパッケージ(最新1.0.1)は3.4より前の環境向けの移植版で、今のPythonに入れる意味はありません。

Python 3.14の仮想環境に入れてみると、インストール自体は成功し、通常は標準ライブラリ側が読み込まれるため何も起きません。ただしPYTHONPATHでsite-packagesを先に探させると、移植版のfrom collections import Sequenceが失敗してImportErrorになります。入れてしまった場合はpip uninstall pathlibで外してください。

よくある質問

os.mkdirとos.makedirsの違いは何ですか?

os.mkdirは指定した1階層だけを作り、親フォルダが無ければFileNotFoundErrorになります。os.makedirsは途中の階層もまとめて作り、exist_ok=Trueで既存フォルダのエラーも止められます。

mkdir(parents=True, exist_ok=True)は何をしますか?

parents=Trueは足りない親フォルダを作り、exist_ok=Trueはフォルダがすでにあってもエラーにしない指定です。組み合わせるとmkdir -pと同じく「無ければ途中から全部作る・あれば何もしない」動きになります。同名のファイルがある場合だけはFileExistsErrorになります。

作成したフォルダを削除するにはどうしますか?

空のフォルダはPath.rmdir()かos.rmdir()で削除できます。中身が残っているとOSError(macOSではErrno 66)になるので、中身ごと消すときはshutil.rmtree()を使います。rmtreeは元に戻せないため、削除するパスを変数で組み立てる場合は事前に出力して確かめてください。

フォルダをコピー・移動するにはどうしますか?

フォルダごとのコピーはshutil.copytree()、移動はshutil.move()です。Python 3.14からはPath.copy()・Path.move()も使えますが、3.13以前には無いため、対応版が混在する環境ではshutilのほうが確実です。

pathlibとosのどちらでフォルダを作るべきですか?

既存コードでは周囲の書き方に合わせ、新規コードでパスの結合やファイル作成も行うならpathlibを選びます。

関連記事

お気に入りに入れた記事の一覧

一創の公式 SNS

X では毎朝の新着記事と IT ニュースの速報を、YouTube・TikTok・Instagram・LinkedIn・Facebook では記事の解説動画を配信しています。

この記事は以下の記事からリンクされています

資料請求

今日のトレンド記事 直近 24 時間で、いつもより多く読まれている記事

  1. 2026.10.29 テックブログ ソニー生命の情報漏洩38.5万件|ログインできない理由、再開状況と窓口の電話番号
  2. 2026.11.03 テックブログ ノジマ不正アクセスで約700万件漏えい:対象確認・窓口と乗っ取り注文を止める実装
  3. 2026.11.03 テックブログ クラブツーリズム不正アクセス:約432万件の対象確認と偽メールの見分け方・流出検知の設計
  4. 2026.11.02 テックブログ サントリーの不正アクセスで約10万人分漏えい|M365のファイル大量ダウンロードを監査ログで調べる手順
  5. 2026.11.02 テックブログ アララの不正アクセス:メール約7,700万件の持ち出しと契約企業が行うAPIキー再設定・代替送信・連名報告

RELATED POSTS 関連記事

目次