Python pathlibでフォルダを作成・削除する方法|mkdir(parents=True, exist_ok=True)とrmdir・rmtree

pathlibでフォルダ(ディレクトリ)を作るにはPath("フォルダ名").mkdir()を使い、途中の階層もまとめて作りたいときはmkdir(parents=True, exist_ok=True)と書きます。削除は空のフォルダならPath.rmdir()、中身ごと消すならshutil.rmtree()です。

この記事ではPath.mkdir()の3つの引数(parents・exist_ok・mode)がそれぞれ何を防ぐのかを、エラーが出る場面と出ない場面の両方を実行して確かめます。Python 3.14で入ったPath.copy()・Path.move()や、2026年10月9日に公開されたPython 3.15の新引数parent_modeにも触れます。実行はmacOS上のPython 3.15.0(比較用に3.13.16)で行いました(2026年10月14日確認)。

os.mkdir()とos.makedirs()の違いはPythonでフォルダ作成|os.mkdirとos.makedirsの違い、pathlib全体の使い方はPython pathlibとは?にまとめています。

Path.mkdir()の書式と引数

公式ドキュメントでの書式は次のとおりです(Python公式ドキュメント pathlib)。

Path.mkdir(mode=0o777, parents=False, exist_ok=False, *, parent_mode=None)
引数既定値Trueや値を指定したときの動き
parentsFalse途中のフォルダがなければまとめて作る(シェルのmkdir -pに相当)。FalseのままだとFileNotFoundError
exist_okFalse同名のフォルダがすでにあってもエラーにしない。FalseのままだとFileExistsError
mode0o777作るフォルダの権限。実際にはプロセスのumaskと組み合わされる
parent_modeNonePython 3.15で追加。parents=Trueで作る途中のフォルダの権限

迷ったらmkdir(parents=True, exist_ok=True)と書けば、「途中がない」「もうある」の両方でエラーになりません。ただし、どちらのエラーも本来は異常を知らせるものなので、意図して無視したいときだけ付けるのが安全です。

基本:フォルダを1つ作る

from pathlib import Path

d = Path("output")
d.mkdir()
print(d.is_dir())

try:
    d.mkdir()
except FileExistsError as e:
    print("FileExistsError:", e)

d.mkdir(exist_ok=True)
print("exist_ok=True なら何も起きない")

実行結果:

True
FileExistsError: [Errno 17] File exists: 'output'
exist_ok=True なら何も起きない

2回目のmkdir()は、同じ名前のフォルダがあるのでFileExistsErrorになります。exist_ok=Trueを付けると、すでにある場合は何もせずに終わります。

parents=True:途中の階層もまとめて作る

「pathlib mkdir parents」で検索されることが多いのがこの引数です。data/2026/10/rawのように深いパスを作るとき、dataがまだなければparents=False(既定)では失敗します。

from pathlib import Path

deep = Path("data") / "2026" / "10" / "raw"
try:
    deep.mkdir()
except FileNotFoundError as e:
    print("FileNotFoundError:", e)

deep.mkdir(parents=True, exist_ok=True)
print(sorted(str(p) for p in Path("data").rglob("*")))

実行結果:

FileNotFoundError: [Errno 2] No such file or directory: 'data/2026/10/raw'
['data/2026', 'data/2026/10', 'data/2026/10/raw']

parents=Trueを付けた2回目で、data・2026・10・rawがまとめて作られました。パスは/演算子でつなぐと、WindowsでもmacOSでも区切り文字を気にせずに書けます。

exist_ok=Trueでも防げないエラー

exist_ok=Trueが無視するのは「同じ名前のフォルダがある」場合だけです。同じ名前のファイルがあると、やはりFileExistsErrorになります。公式ドキュメントにも、パスが存在してディレクトリでない場合はエラーになると書かれています。

from pathlib import Path

f = Path("memo.txt")
f.write_text("hello")
try:
    f.mkdir(exist_ok=True)
except FileExistsError as e:
    print("FileExistsError:", e)

実行結果:

FileExistsError: [Errno 17] File exists: 'memo.txt'

パスの途中にファイルがあるときに出る別のエラーはNotADirectoryErrorの原因と対処法で扱っています。

mode:権限を指定して作る(macOS・Linux)

modeは、そのまま権限になるわけではなく、プロセスのumask(外す権限の指定)と組み合わされます。umaskを0o022にして試しました。

from pathlib import Path
import os

old = os.umask(0o022)
p = Path("private")
p.mkdir(mode=0o700)
print(oct(p.stat().st_mode & 0o777))

q = Path("public")
q.mkdir(mode=0o777)
print(oct(q.stat().st_mode & 0o777))
os.umask(old)

実行結果:

0o700
0o755

0o700(自分だけ読み書き可能)はそのまま反映されましたが、0o777を指定したほうはumaskで書き込み権限が外れて0o755になりました。確実に特定の権限にしたい場合は、作った後にPath.chmod()で設定し直します。Windowsではこの権限の仕組みが異なるため、modeの効果は限られます。

Python 3.15の新引数parent_mode

parents=Trueで作る途中のフォルダは、これまでmodeの影響を受けず既定の権限で作られていました。Python 3.15では途中のフォルダの権限を指定するparent_modeが追加されています(公式ドキュメント、3.15.0はpython.orgで2026年10月9日公開)。

from pathlib import Path
import os

os.umask(0o022)
p = Path("pm/a/b")
p.mkdir(parents=True, parent_mode=0o700, mode=0o755)
print(oct(Path("pm").stat().st_mode & 0o777),
      oct(Path("pm/a").stat().st_mode & 0o777),
      oct(p.stat().st_mode & 0o777))

Python 3.15.0での実行結果:

0o700 0o700 0o755

途中のpmとpm/aは0o700、最後のbはmodeどおり0o755になりました。Python 3.13で同じコードを実行すると次のエラーになるので、使うのは3.15以降の環境に限られます。

TypeError: Path.mkdir() got an unexpected keyword argument 'parent_mode'

フォルダを削除する:rmdir()とshutil.rmtree()

pathlibのPath.rmdir()が消せるのは空のフォルダだけです。中にファイルやフォルダがあるとOSError(ディレクトリが空でない)になります。中身ごと消すには標準ライブラリのshutil.rmtree()を使います。

from pathlib import Path
import shutil

empty = Path("empty_dir")
empty.mkdir()
empty.rmdir()
print("空のフォルダを削除:", empty.exists())

full = Path("full_dir")
(full / "sub").mkdir(parents=True)
(full / "sub" / "a.txt").write_text("x")
try:
    full.rmdir()
except OSError as e:
    print(type(e).__name__, e)

shutil.rmtree(full)
print("rmtreeで削除:", full.exists())

実行結果(macOS):

空のフォルダを削除: False
OSError [Errno 66] Directory not empty: 'full_dir'
rmtreeで削除: False

エラー番号とメッセージはOSによって変わります。Python 3.15.0で確認した時点でも、pathlibには中身ごと消す公開メソッドはありません。shutil.rmtree()は確認なしで中身をすべて消し、ごみ箱にも入らないので、パスを変数で組み立てるときは消す前にprint()で中身を確かめる習慣を付けてください。ファイル単体の削除(Path.unlink())を含む削除方法の全体はPythonでファイル・フォルダを削除する方法で比較しています。

やりたいこと使うもの注意点
空のフォルダを消すPath.rmdir()中身があるとOSError
フォルダを中身ごと消すshutil.rmtree(path)元に戻せない
ファイルを消すPath.unlink(missing_ok=True)フォルダには使えない
処理の後に自動で消える作業用フォルダtempfile.TemporaryDirectory()with文を抜けると削除される

Python 3.14以降:Path.copy()とPath.move()

Python 3.14から、pathlibだけでフォルダを中身ごとコピー・移動できるようになりました。copy()・copy_into()・move()・move_into()の4つです(公式ドキュメント)。

from pathlib import Path

src = Path("work")
(src / "img").mkdir(parents=True, exist_ok=True)
(src / "img" / "a.png").write_bytes(b"\x89PNG")
(src / "note.txt").write_text("memo")

Path("backup").mkdir(exist_ok=True)
copied = src.copy(Path("backup") / "work")
print("copy:", sorted(str(p) for p in copied.rglob("*")))

Path("archive").mkdir(exist_ok=True)
moved = src.move_into("archive")
print("move_into:", moved, src.exists())

Python 3.15.0での実行結果:

copy: ['backup/work/img', 'backup/work/img/a.png', 'backup/work/note.txt']
move_into: archive/work False

注意点が1つあります。copy()のコピー先の親フォルダ(この例のbackup)がないと、FileNotFoundErrorになりました。copy()はコピー先を作るときに途中の階層までは作らないので、先にmkdir(parents=True, exist_ok=True)で用意します。move_into()は指定したフォルダの中へ移すメソッドで、移動後は元のworkがなくなっています。

Python 3.13以前ではcopy()がないため、次のエラーになります。古い環境ではshutil.copytree()・shutil.move()を使ってください(shutil.copyとcopytreeの違い)。

AttributeError: 'PosixPath' object has no attribute 'copy'

実用例:プロジェクトのフォルダ構成を一度に作る

from pathlib import Path

base = Path("myproject")
for sub in ["src", "tests", "docs", "data/raw", "data/processed"]:
    (base / sub).mkdir(parents=True, exist_ok=True)
(base / "README.md").touch()

for p in sorted(base.rglob("*")):
    depth = len(p.relative_to(base).parts) - 1
    print("  " * depth + p.name + ("/" if p.is_dir() else ""))

実行結果:

README.md
data/
  processed/
  raw/
docs/
src/
tests/

parents=True, exist_ok=Trueにしているので、何度実行しても同じ結果になり、既存のファイルも壊しません。rglob("*")で配下をすべてたどる方法はpathlibでファイル一覧を取得する方法で詳しく扱っています。

実用例:処理が終わったら消える作業用フォルダ

一時的なフォルダを自分でmkdir()して最後にrmtree()するより、標準ライブラリのtempfile.TemporaryDirectory()を使うほうが、途中で例外が起きても確実に後片付けされます。

import tempfile
from pathlib import Path

with tempfile.TemporaryDirectory() as tmp:
    work = Path(tmp) / "step1"
    work.mkdir()
    (work / "result.csv").write_text("a,b\n1,2\n")
    print(work.exists(), [p.name for p in work.iterdir()])
print("with を抜けた後:", work.exists())

実行結果:

True ['result.csv']
with を抜けた後: False

詳しくはPython TemporaryDirectoryとは?をご覧ください。

エラー別の対処まとめ

エラー起きる場面対処
FileExistsError同名のフォルダ、または同名のファイルがあるフォルダならexist_ok=True。ファイルなら名前を変える
FileNotFoundError途中のフォルダがない/copy()の親フォルダがないparents=Trueで親を作る
OSError(空でない)中身のあるフォルダをrmdir()shutil.rmtree()を使う
PermissionError書き込み権限のない場所に作る・消す保存先を見直す。管理者権限で実行しない
AttributeError(copy・move)Python 3.13以前shutilの関数を使う

相対パスで指定したフォルダは「今いる場所(カレントディレクトリ)」を基準に作られます。思った場所にできないときはカレントディレクトリを取得・移動する方法を確認してください。

エラーの意味を1つずつ確かめながら書く練習は、独学だと時間がかかりがちです。テックジムは東京・永田町の東京本校に通う対面型のプログラミングスクールで、自分のペースで課題を進め、詰まったところをトレーナーに質問できます。まずは無料講座で雰囲気を確かめてみてください。

よくある質問

Q. pathlibでmkdirするとFileNotFoundErrorになります。

作ろうとしているフォルダの途中の階層がまだないためです。mkdir(parents=True)を指定すると、途中のフォルダもまとめて作られます。

Q. exist_ok=Trueを付けたのにFileExistsErrorが出ます。

同じ名前のファイルがあるときです。exist_ok=Trueが無視するのは同名のフォルダがある場合だけで、ファイルがあるとエラーになります。

Q. pathlibだけで中身のあるフォルダを削除できますか?

Python 3.15時点でもできません。Path.rmdir()は空のフォルダ専用なので、中身ごと消すにはshutil.rmtree()を使います。

Q. Path.mkdir()とos.makedirs()はどちらを使えばよいですか?

動きはほぼ同じで、Path.mkdir(parents=True, exist_ok=True)がos.makedirs(path, exist_ok=True)に当たります。パスをPathオブジェクトで扱っているならPath.mkdir()を使うと書き方が揃います。

Q. Path.copy()が使えません。

Path.copy()とPath.move()はPython 3.14で追加されたメソッドです。3.13以前ではAttributeErrorになるので、shutil.copytree()やshutil.move()を使ってください。

あわせて読みたい

学習の順序はPython学習のロードマップ、標準で使える機能の一覧はPython標準ライブラリのモジュール一覧にまとめています。

プログラミング学習に興味がある方は、まずは無料体験会へ

無料体験会・お申し込みはこちら