「スマホから取り込んだ写真が IMG_0012.JPG だらけで、いつの写真か分からない…」「ファイル名を1個ずつ手で変えるのがつらい」

こういう地味な作業、意外と時間を取られますよね。

この記事では、Python の標準ライブラリだけでフォルダ内のファイル名を「日付+連番」に一括リネームするスクリプトを作ります。ただ名前を変えるだけでなく、

  • いきなり変えずに「変更予定」だけを表示するお試しモード
  • 同じ名前のファイルを上書きしない安全チェック
  • 失敗しても元の名前に戻せる記録(CSV)

まで入れて、「うっかり大事なファイルを壊した…」を防ぐ形にします。一緒に見ていきましょう!

難易度:初級(for文・if文・リストが分かる方向け。追加のインストールは不要です)。動作確認は Python 3.13(Windows)で行いました。

ファイル名の一括リネームで気をつけること

organizing photo files on laptop
organizing photo files on laptop / Photo by Ron Lach via Pexels

リネームは一瞬で終わる処理ですが、やり直しがききにくいのが怖いところです。イメージとしては「消しゴムなしでボールペン清書する」ようなものですね。

そこで今回は、次の3段階で進めます👇

  1. 練習用のフォルダを作って試す(いきなり本物の写真フォルダで実行しない)
  2. お試しモードで変更予定を目で確認する
  3. 本番実行するときは変更前後の名前をCSVに記録し、いつでも元に戻せるようにする

使うのは pathlib(ファイル・フォルダ操作)、datetime(日付)、csv(記録)の3つだけです。

ステップ1:練習用のファイルを作る

まずは練習用に photos フォルダを作り、ダミーのファイルを5つ置きます。os.utime() を使うと、ファイルの更新日時を好きな日時に書き換えられるので、「撮った日がバラバラの写真」を再現できます。

# 練習用のファイルを作るスクリプト(本物の写真フォルダで試す前に!)
import os
from datetime import datetime
from pathlib import Path

folder = Path("photos")
folder.mkdir(exist_ok=True)

# (ファイル名, 更新日時)の組み合わせ
samples = [
    ("IMG_0012.JPG", "2026-09-28 10:15"),
    ("IMG_0013.jpg", "2026-09-28 10:16"),
    ("DSC00451.jpg", "2026-10-03 18:40"),
    ("スクリーンショット 2026-10-05.png", "2026-10-05 09:02"),
    ("memo.txt", "2026-10-05 12:00"),
]

for name, stamp in samples:
    path = folder / name
    path.write_text("dummy", encoding="utf-8")
    t = datetime.strptime(stamp, "%Y-%m-%d %H:%M").timestamp()
    os.utime(path, (t, t))  # 更新日時を書き換える

print(sorted(p.name for p in folder.iterdir()))

実行すると、photos フォルダに IMG_0012.JPG・IMG_0013.jpg・DSC00451.jpg・スクリーンショット 2026-10-05.png・memo.txt の5つができます。拡張子の大文字・小文字が混ざっているのもポイントです。

ステップ2:お試しモードで変更予定を確認する

ここがメインのスクリプトです。ポイントをまとめるとこんな感じです👇

  • TARGET_EXTS で画像(jpg・jpeg・png)だけを対象にする(memo.txt は変えない)
  • p.suffix.lower() で拡張子を小文字にそろえて比べるので、.JPG も対象になる
  • ファイルを更新日時の古い順に並べ、日付ごとに 001, 002… と連番をふる
  • DRY_RUN = True の間は表示するだけで、ファイルには一切さわらない
import csv
from datetime import datetime
from pathlib import Path

FOLDER = Path("photos")
TARGET_EXTS = {".jpg", ".jpeg", ".png"}  # 画像だけを対象にする
DRY_RUN = True  # True の間は「予定」を表示するだけ。確認できたら False に

# 対象ファイルを更新日時の古い順に並べる
files = sorted(
    (p for p in FOLDER.iterdir() if p.is_file() and p.suffix.lower() in TARGET_EXTS),
    key=lambda p: p.stat().st_mtime,
)

plan = []      # (元のパス, 新しいパス)
counters = {}  # 日付ごとの連番
for p in files:
    day = datetime.fromtimestamp(p.stat().st_mtime).strftime("%Y-%m-%d")
    counters[day] = counters.get(day, 0) + 1
    new_name = f"{day}_{counters[day]:03d}{p.suffix.lower()}"
    plan.append((p, p.with_name(new_name)))

# 名前がかぶるファイルがないかチェック(上書き事故を防ぐ)
for old, new in plan:
    if new != old and new.exists():
        raise SystemExit(f"中止: {new.name} はすでに存在します")

for old, new in plan:
    print(f"{old.name} -> {new.name}")

if DRY_RUN:
    print(f"\n[お試しモード] {len(plan)}件の変更予定を表示しました(まだ何も変えていません)")
else:
    # 元に戻せるように、変更前後の名前をCSVに記録してからリネーム
    with open("rename_log.csv", "w", newline="", encoding="utf-8") as f:
        writer = csv.writer(f)
        writer.writerow(["old", "new"])
        for old, new in plan:
            writer.writerow([old.name, new.name])
            old.rename(new)
    print(f"\n{len(plan)}件をリネームしました(記録: rename_log.csv)")
実行結果:お試しモードで変更予定を表示
実行結果:お試しモードで変更予定を表示

実行結果はこうなりました。

memo.txt はちゃんと対象外になり、同じ日(9月28日)の2枚には _001 と _002 が付いています。IMG_0012.JPG の拡張子も .jpg にそろいました😊

ここが重要です👇 このスクリプトは何も変えずに「予定」だけを出しています。まず表示を見て、「意図どおりか?」を確認するクセをつけておくと安心です。

本番実行:DRY_RUN を False にする

予定に問題がなければ、DRY_RUN = False に書き換えてもう一度実行します。今回の環境では「4件をリネームしました(記録: rename_log.csv)」と表示され、フォルダの中身は次のようになりました。

  • 2026-09-28_001.jpg / 2026-09-28_002.jpg
  • 2026-10-03_001.jpg / 2026-10-05_001.png
  • memo.txt(そのまま)

同時に作られる rename_log.csv には、old,new の見出しの下に「元の名前,新しい名前」が1行ずつ記録されます。

上書き事故を防ぐチェックの意味

スクリプトの途中にある「名前がかぶるファイルがないかチェック」は、地味ですがとても大事です。

実は Path.rename() は、変更先に同じ名前のファイルがあったときの動きが OS によって違います。公式ドキュメントによると、Windows ではエラー(FileExistsError)になりますが、Mac や Linux では黙って上書きされます⚠️

実際に、リネーム済みのフォルダに「9月28日 8:00 の写真(IMG_0001.jpg)」を追加してもう一度実行してみると、新しい写真が 2026-09-28_001.jpg になろうとして既存のファイルとぶつかるため、次のように1件も変えずに止まりました。

中止: 2026-09-28_001.jpg はすでに存在します

つまり「迷ったら止まる」設計にしておけば、OS の違いを気にせず安全に使えるということです。

ステップ3:記録CSVを使って元に戻す

「やっぱり元の名前に戻したい!」というときのためのスクリプトです。

  • csv.DictReader で記録を読み、row["old"]・row["new"] で取り出す
  • reversed() で後から変えたものから順に戻す
  • 戻し先にすでにファイルがある場合などは、無理に戻さずスキップする
import csv
from pathlib import Path

FOLDER = Path("photos")

with open("rename_log.csv", newline="", encoding="utf-8") as f:
    rows = list(csv.DictReader(f))

count = 0
for row in reversed(rows):  # 後から変えたものから順に戻す
    new_path = FOLDER / row["new"]
    old_path = FOLDER / row["old"]
    if new_path.exists() and not old_path.exists():
        new_path.rename(old_path)
        count += 1
    else:
        print(f"スキップ: {row['new']}")

print(f"{count}件を元の名前に戻しました")
print(sorted(p.name for p in FOLDER.iterdir()))
実行結果:記録CSVから元の名前に戻す
実行結果:記録CSVから元の名前に戻す

実行結果はこうなりました。4件すべてが元の名前に戻り、ステップ1で作った直後と同じ状態になっています。

これ、本番で使う前に「リネーム → 元に戻す」を練習用フォルダで一度やっておくのがおすすめです。戻せることが分かっていると、安心して本物のフォルダに使えますよ🚀

自分のフォルダで使うときの注意点

  • まずはコピーしたフォルダで試す:FOLDER = Path("photos") を自分のフォルダのパスに変えるだけで動きますが、最初はバックアップを取ってからにしましょう
  • 更新日時=撮影日とは限らない:コピーやダウンロードの方法によっては、更新日時がその作業をした日時に変わることがあります。お試しモードの表示で日付がおかしくないか確認してください
  • 命名ルールは1行で変えられる:new_name の f文字列を f"旅行_{day}_{counters[day]:03d}{p.suffix.lower()}" のように変えれば、先頭に好きな文字を付けられます
  • rename_log.csv は上書きされる:本番実行のたびに作り直されるので、元に戻したいときは次の本番実行の前に戻しましょう

まとめ

今回は、Python の標準ライブラリだけでファイル名を一括リネームするスクリプトを作りました。ポイントをおさらいしましょう👇

  • pathlib の iterdir()・suffix・stat().st_mtime・rename() でファイル情報の取得と名前変更ができる
  • お試しモード(DRY_RUN)で変更予定を先に確認する
  • Path.rename() は OS によって上書きの動きが違うので、名前の衝突は自分でチェックして止める
  • 変更前後の名前をCSVに記録しておけば、いつでも元に戻せる

写真の整理だけでなく、請求書やスキャンした書類の整理にもそのまま応用できます。「むずかしそう」を「できそう」に変える第一歩として、ぜひ練習用フォルダで試してみてください😊

\ 読んだら、次は自分で作ってみよう /

筆者が運営する無料の入門コース「作って学ぶPythonプログラミング入門」では、こうした基本文法を、割り勘計算機・おみくじ・数当てゲームなどを作りながら身につけます。各章末の定着ドリル(全42問)で、自分の手で書く練習まで。最初の4レッスンは登録なしで読めます。

→ 無料の入門コース(全7章52レッスン)を見てみる

📚 関連商品・おすすめ書籍

スッキリわかるPython入門 第2版 (スッキリわかる入門シリーズ)

もしも

スッキリわかるPython入門 第2版 (スッキリわかる入門シリーズ)

初心者に定番のPython入門書

Amazonで見る
徹底攻略! 電子工作&プログラミング Arduinoで学ぶ電子工作完全ガイド

もしも

徹底攻略! 電子工作&プログラミング Arduinoで学ぶ電子工作完全ガイド

電子工作とプログラミングを同時に学べる

Amazonで見る
実践Claude Code入門―現場で活用するためのAIコーディングの思考法

もしも

実践Claude Code入門―現場で活用するためのAIコーディングの思考法

AIコーディングの現場活用法を学ぶ一冊

Amazonで見る

※本記事にはアフィリエイトリンクが含まれます。

ABOUT ME
やまちゃん
これまで学生と社会人を合わせて5000人以上にプログラミング学習を指導。 ゼロからイチをわかりやすく解説する専門家として活動しており、本業ではArduinoを用いたIoT開発とロボットプログラミングが専門。 Pythonを用いたアプリ開発、ウェブアプリケーションの開発で業務の効率化をサポートしています。