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や値を指定したときの動き |
|---|---|---|
parents | False | 途中のフォルダがなければまとめて作る(シェルのmkdir -pに相当)。FalseのままだとFileNotFoundError |
exist_ok | False | 同名のフォルダがすでにあってもエラーにしない。FalseのままだとFileExistsError |
mode | 0o777 | 作るフォルダの権限。実際にはプロセスのumaskと組み合わされる |
parent_mode | None | Python 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標準ライブラリのモジュール一覧にまとめています。




