旅行や日常生活で撮影した写真が増えてくると、目的の写真を探すのが大変になりませんか?
スマートフォンやデジタルカメラで撮影した写真をパソコンに保存していると、何百枚、何千枚と写真がたまり、整理するだけでも時間がかかってしまいます。
そんなときに便利なのが、Pythonを使った写真の自動整理です。
Pythonを使えば、写真ファイルの日付情報を取得し、撮影日やファイルの更新日ごとにフォルダを作成して、自動で分類できます。
例えば、整理前は1つのフォルダに保存されていた写真を、次のように分類できます。
- 2030-12-01
- 2030-12-02
- 2030-12-03
この記事では、Python初心者向けに、写真を日付別フォルダに自動整理する方法を基礎から解説します。
実際に動かせるPythonコードを掲載し、フォルダの準備、コードの意味、実行結果、エラーへの対処法まで詳しく紹介します。
さらに、応用編では写真に記録されたEXIF情報から撮影日時を取得する方法も解説します。
Pythonを使って写真整理を効率化したい方は、ぜひ参考にしてください。
Pythonで写真を日付別フォルダに自動整理するメリット
写真整理を手作業で行うデメリット
旅行の写真や日常の写真を整理するとき、手作業でフォルダを作成して分類している方も多いのではないでしょうか。
しかし、写真の枚数が増えるほど、手作業による整理には時間がかかります。
例えば、次のような悩みがあります。
- 写真が多く、1枚ずつ確認するのが大変
- 撮影日が異なる写真が同じフォルダに混在している
- 旅行ごとに写真を探すのに時間がかかる
- 新しい写真を追加するたびに整理し直す必要がある
- 写真の整理を後回しにしてしまう
このような作業は、Pythonで自動化できます。
Pythonで自動化できること
Pythonを使うと、写真整理に関するさまざまな作業を効率化できます。
例えば、次のような処理が可能です。
- 写真ファイルの日付情報を取得する
- 日付別のフォルダを自動で作成する
- 写真を対応するフォルダへコピーする
- 写真が保存されているフォルダをまとめて処理する
- 写真の一覧をCSVファイルに出力する
- EXIF情報から実際の撮影日時を取得する
一度プログラムを作成しておけば、写真が増えたときにも同じ処理を繰り返し実行できます。
プログラミング初心者でも、基本的なコードから少しずつ機能を追加していけば、実用的な写真整理ツールを作れます。
この記事で作るプログラムの完成イメージ
この記事では、最初にファイルの更新日時を使って写真を分類するプログラムを作ります。
例えば、整理前のフォルダが次のようになっているとします。
photos/
├── travel_001.jpg
├── travel_002.jpg
├── travel_003.jpg
├── landscape.png
└── memory.jpegPythonを実行すると、日付別のフォルダが作成され、写真がコピーされます。
organized_photos/
├── 2030-12-01/
│ ├── travel_001.jpg
│ └── landscape.png
├── 2030-12-02/
│ ├── travel_002.jpg
│ └── memory.jpeg
└── 2030-12-03/
└── travel_003.jpg※上記はフォルダ構成の例です。実際の分類先は、各ファイルの更新日時によって変わります。
なお、最初のプログラムでは、元の写真を移動せずにコピーします。プログラムの動作を確認しやすくするため、まずはテスト用の写真フォルダで試してみましょう。
Pythonで写真を自動整理する準備
Pythonの実行環境を用意する
まずは、Pythonを実行できる環境を用意します。
すでにPythonがインストールされている場合は、この手順を飛ばしても構いません。
Pythonがインストールされていない場合は、Pythonの公式サイトからインストーラーを入手できます。
インストール後、WindowsではコマンドプロンプトやPowerShellを開き、次のコマンドを実行します。
python --version環境によっては、次のコマンドで確認できます。
py --versionバージョン番号が表示されれば、Pythonが利用できる状態です。
この記事の基本編で使用する機能はPythonの標準ライブラリに含まれているため、追加のライブラリをインストールする必要はありません。
テスト用の写真フォルダを作る
次に、整理する写真を保存するフォルダを作成します。
例えば、デスクトップに次のようなフォルダを用意します。
photo_sorting/
├── photos/
└── organize_photos.pyそれぞれの役割は次のとおりです。
- photos:整理したい写真を保存するフォルダ
- organize_photos.py:写真整理のプログラム
最初は、数枚のテスト用画像だけをphotosフォルダに入れてください。
プログラムが正常に動作することを確認してから、本番の写真フォルダに適用するのがおすすめです。
写真のコピー先フォルダを準備する
整理後の写真を保存するフォルダも決めておきましょう。
この記事では、次のフォルダをコピー先として使用します。
photo_sorting/
├── photos/
├── organized_photos/
└── organize_photos.pyorganized_photosフォルダは、プログラムが自動的に作成するため、事前に用意する必要はありません。
重要なのは、元の写真フォルダと整理後のフォルダを分けることです。
元の写真を残しておけば、分類結果に問題があった場合でも元のデータを確認できます。
Pythonで写真を日付別フォルダに整理する基本コード
写真をコピーして整理するPythonコード
まずは、写真ファイルの更新日時を利用して、日付別のフォルダに写真をコピーするプログラムを作成します。
以下のコードをコピーし、organize_photos.pyという名前で保存してください。
from pathlib import Path
from datetime import datetime
import shutil
# 整理したい写真が保存されているフォルダ
source_folder = Path("photos")
# 整理後の写真を保存するフォルダ
destination_folder = Path("organized_photos")
# 対象にする画像ファイルの拡張子
image_extensions = {
".jpg", ".jpeg", ".png",
".gif", ".bmp", ".webp", ".tif", ".tiff"
}
# コピー先のフォルダを作成
destination_folder.mkdir(parents=True, exist_ok=True)
# 元フォルダが存在するか確認
if not source_folder.is_dir():
raise FileNotFoundError(
f"写真フォルダが見つかりません: {source_folder.resolve()}"
)
# 対象の画像ファイルを取得
for photo in source_folder.iterdir():
# ファイル以外はスキップ
if not photo.is_file():
continue
# 対象外の拡張子はスキップ
if photo.suffix.lower() not in image_extensions:
continue
# ファイルの更新日時を取得
modified_time = datetime.fromtimestamp(
photo.stat().st_mtime
)
# 日付をYYYY-MM-DD形式にする
date_folder_name = modified_time.strftime("%Y-%m-%d")
# 日付別の保存先フォルダを作成
date_folder = destination_folder / date_folder_name
date_folder.mkdir(parents=True, exist_ok=True)
# コピー先のファイルパス
destination_path = date_folder / photo.name
# 同じ名前のファイルがある場合は上書きしない
if destination_path.exists():
print(f"スキップ(同名ファイルあり): {photo.name}")
continue
# 写真をコピー
shutil.copy2(photo, destination_path)
print(f"コピー完了: {photo.name} -> {date_folder_name}")
print("写真の整理が完了しました。")このプログラムは、photosフォルダ内の画像ファイルを確認し、ファイルの更新日時に基づいて日付別のフォルダへコピーします。
元の写真は削除されません。
また、同じ名前のファイルがコピー先に存在する場合はスキップするため、既存ファイルを上書きしません。
コード解説
ここからは、プログラムの重要な部分を順番に解説します。
1. 必要なライブラリを読み込む
from pathlib import Path
from datetime import datetime
import shutilそれぞれの役割は次のとおりです。
- Path:フォルダやファイルのパスを扱う
- datetime:日付や時刻を扱う
- shutil:ファイルをコピーする
どれもPythonの標準ライブラリなので、追加インストールは不要です。
2. 整理元と整理先を指定する
source_folder = Path("photos")
destination_folder = Path("organized_photos")source_folderは、整理したい写真が保存されているフォルダです。
destination_folderは、整理後の写真を保存するフォルダです。
この例では、プログラムと同じ場所にphotosフォルダがあることを想定しています。
写真が別の場所に保存されている場合は、実際のフォルダパスに変更してください。
例えば、Windowsで写真が次の場所にある場合です。
source_folder = Path(r"C:\Users\YourName\Pictures")YourNameの部分は、実際のWindowsユーザー名に置き換えてください。
3. 対象となる画像ファイルを指定する
image_extensions = {
".jpg", ".jpeg", ".png",
".gif", ".bmp", ".webp", ".tif", ".tiff"
}この部分では、整理対象にする画像ファイルの拡張子を指定しています。
拡張子とは、ファイル名の末尾に付いている種類を示す文字列です。
例えば、次のようなものがあります。
- photo.jpg
- landscape.png
- memory.jpeg
拡張子を指定することで、テキストファイルやPDFなどを誤って写真として処理することを防ぎます。
なお、HEIC形式など、ここに含まれていない形式は基本編では対象になりません。
4. ファイルの更新日時を取得する
modified_time = datetime.fromtimestamp(
photo.stat().st_mtime
)ここでは、写真ファイルの更新日時を取得しています。
photo.stat().st_mtimeは、ファイルの最終更新時刻をタイムスタンプとして取得する処理です。
datetime.fromtimestamp()を使うことで、タイムスタンプをPythonで扱いやすい日時に変換しています。
ただし、ファイルの更新日時は、必ずしも写真を撮影した日時とは一致しません。
例えば、写真を別のパソコンにコピーしたり、画像編集ソフトで保存し直したりすると、更新日時が変わることがあります。
実際の撮影日で整理したい場合は、後述するEXIF情報を使う方法がおすすめです。
5. 日付別のフォルダ名を作る
date_folder_name = modified_time.strftime("%Y-%m-%d")strftime()は、日時を指定した形式の文字列に変換するメソッドです。
%Y-%m-%dは、年・月・日を表します。
例えば、2030年12月31日であれば、次のようになります。
2030-12-31日付をこの形式で統一すると、フォルダ名が分かりやすくなり、名前順に並べたときも日付順に整理しやすくなります。
6. 日付別のフォルダを作成する
date_folder = destination_folder / date_folder_name
date_folder.mkdir(parents=True, exist_ok=True)ここでは、整理先のフォルダの中に日付別のフォルダを作成しています。
Pathの / 演算子は、パスを組み立てるために使います。
例えば、次の2つを組み合わせると、
organized_photos
2030-12-31次のようなパスになります。
organized_photos/2030-12-31mkdir()はフォルダを作成するメソッドです。
parents=Trueは、必要な親フォルダも作成する指定です。
exist_ok=Trueは、すでにフォルダが存在していてもエラーにしない指定です。
同じ日付の写真が複数ある場合も、同じフォルダにまとめられます。
7. 写真をコピーする
shutil.copy2(photo, destination_path)この処理で、元の写真を整理先のフォルダにコピーします。
copy2()は、可能な範囲で元ファイルの更新日時などのメタデータも保持しながらコピーする関数です。
元の写真は残るため、初めてプログラムを試す場合にも使いやすい方法です。
実行方法と実行結果
コードを保存したら、コマンドプロンプトやターミナルでphoto_sortingフォルダに移動します。
そのうえで、次のコマンドを実行してください。
python organize_photos.py環境によっては、次のコマンドでも実行できます。
py organize_photos.py正常に動作すると、例えば次のようなメッセージが表示されます。
コピー完了: travel_001.jpg -> 2030-12-01
コピー完了: travel_002.jpg -> 2030-12-02
コピー完了: landscape.png -> 2030-12-01
写真の整理が完了しました。※これは動作を説明するための出力例です。実際の表示内容は、写真のファイル名や更新日時によって変わります。
実行後は、organized_photosフォルダを開いて、日付別のフォルダが作成されているか確認しましょう。
年・月・日ごとのフォルダを作成する方法
日付別に分類するだけでなく、年・月・日ごとに階層を分けたい場合もあります。
例えば、次のようなフォルダ構成です。
organized_photos/
└── 2030/
└── 12/
├── 01/
├── 02/
└── 03/このような構成にしたい場合は、基本コードのフォルダ名を作成する部分を次のように変更できます。
date_folder = (
destination_folder
/ modified_time.strftime("%Y")
/ modified_time.strftime("%m")
/ modified_time.strftime("%d")
)
date_folder.mkdir(parents=True, exist_ok=True)これで、年・月・日ごとに階層化されたフォルダが作成されます。
写真の枚数が多い場合や、何年分もの写真を管理したい場合に便利な方法です。
写真の撮影日時を取得して整理する方法
基本編ではファイルの更新日時を利用しましたが、旅行写真などを整理する場合は、実際に撮影した日時で分類したいこともあるでしょう。
その場合は、写真に保存されているEXIF情報を利用します。
ファイルの更新日時と撮影日時の違い
写真に関する日時には、いくつかの種類があります。
| 日時の種類 | 意味 |
|---|---|
| ファイルの更新日時 | ファイルが最後に変更された日時 |
| EXIFの撮影日時 | 写真データに記録された撮影日時 |
| ファイルの作成日時 | ファイルシステム上で作成された日時。コピー時などに変わる場合がある |
例えば、2030年8月に撮影した写真を、2030年12月にパソコンへコピーしたとします。
この場合、撮影日時は8月でも、ファイルの更新日時は12月になっている可能性があります。
そのため、旅行日や撮影日ごとに整理したい場合は、EXIFの撮影日時を使う方法が適しています。
ただし、すべての写真に撮影日時が記録されているわけではありません。SNSからダウンロードした画像や編集済みの画像では、EXIF情報が削除されていることもあります。
EXIF情報から撮影日時を取得する方法
EXIF情報を読み取るには、画像処理ライブラリのPillowを利用できます。
まず、ターミナルで次のコマンドを実行してください。
python -m pip install Pillow次に、撮影日時を取得する基本コードを紹介します。
from pathlib import Path
from PIL import Image
from PIL.ExifTags import TAGS
from datetime import datetime
def get_taken_date(photo_path):
"""写真のEXIF情報から撮影日時を取得する。"""
try:
with Image.open(photo_path) as image:
exif_data = image.getexif()
for tag_id, value in exif_data.items():
tag_name = TAGS.get(tag_id, tag_id)
if tag_name == "DateTimeOriginal":
return datetime.strptime(
str(value),
"%Y:%m:%d %H:%M:%S"
)
except (OSError, ValueError, TypeError):
pass
return None
photo_path = Path("photos/travel_001.jpg")
taken_date = get_taken_date(photo_path)
if taken_date is not None:
print("撮影日時:", taken_date)
else:
print("撮影日時を取得できませんでした。")このコードでは、写真のEXIF情報を調べ、DateTimeOriginalという項目から撮影日時を取得しています。
DateTimeOriginalは、撮影時刻を記録するための代表的なEXIFタグです。
例えば、撮影日時が2030年12月1日15時30分だった場合、次のような結果が得られます。
撮影日時: 2030-12-01 15:30:00※表示例です。実際の結果は写真のEXIF情報によって変わります。
撮影日時が取得できなかった場合はNoneが返されます。そのため、EXIF情報が存在しない写真を処理するときも、取得結果を確認することが大切です。
なお、上記のコードは基本的なEXIF情報を対象としています。すべての画像形式や特殊なメタデータに対応するものではありません。
撮影日時を使って写真を整理する方法
撮影日時を取得できるようになったら、先ほどの写真整理プログラムに組み込めます。
以下は、撮影日時が取得できた写真を撮影日別のフォルダにコピーする例です。EXIF情報が取得できない場合は、ファイルの更新日時を代わりに使用します。
from pathlib import Path
from datetime import datetime
import shutil
from PIL import Image
from PIL.ExifTags import TAGS
source_folder = Path("photos")
destination_folder = Path("organized_photos")
image_extensions = {
".jpg", ".jpeg", ".png",
".gif", ".bmp", ".webp", ".tif", ".tiff"
}
def get_taken_date(photo_path):
"""EXIF情報から撮影日時を取得する。"""
try:
with Image.open(photo_path) as image:
exif_data = image.getexif()
for tag_id, value in exif_data.items():
tag_name = TAGS.get(tag_id, tag_id)
if tag_name == "DateTimeOriginal":
return datetime.strptime(
str(value),
"%Y:%m:%d %H:%M:%S"
)
except (OSError, ValueError, TypeError):
pass
return None
if not source_folder.is_dir():
raise FileNotFoundError(
f"写真フォルダが見つかりません: {source_folder.resolve()}"
)
destination_folder.mkdir(parents=True, exist_ok=True)
for photo in source_folder.iterdir():
if not photo.is_file():
continue
if photo.suffix.lower() not in image_extensions:
continue
# 最初にEXIFの撮影日時を取得する
taken_date = get_taken_date(photo)
if taken_date is not None:
target_date = taken_date
date_source = "撮影日時"
else:
# 取得できない場合は更新日時を使用
target_date = datetime.fromtimestamp(
photo.stat().st_mtime
)
date_source = "更新日時"
date_folder_name = target_date.strftime("%Y-%m-%d")
date_folder = destination_folder / date_folder_name
date_folder.mkdir(parents=True, exist_ok=True)
destination_path = date_folder / photo.name
if destination_path.exists():
print(f"スキップ(同名ファイルあり): {photo.name}")
continue
shutil.copy2(photo, destination_path)
print(
f"コピー完了: {photo.name} -> "
f"{date_folder_name}({date_source})"
)
print("写真の整理が完了しました。")このコードを使う場合は、Pillowをインストールしておく必要があります。
また、EXIF情報がない写真では更新日時が使われるため、すべての写真が実際の撮影日で分類されるとは限りません。表示されたログも確認し、必要に応じて手動で整理してください。
Pythonによる写真整理を安全に使う方法
写真整理の自動化は便利ですが、大切な写真を誤って上書きしたり、想定と異なるフォルダに保存したりしないように注意が必要です。
元の写真を残したまま整理する
初めてプログラムを実行するときは、必ずテスト用フォルダを使用しましょう。
この記事のコードは写真をコピーする方式なので、元の写真は削除されません。
ただし、コピー先の設定を誤ると、意図しない場所にファイルが作成される可能性があります。
最初に少数の写真でテストし、フォルダ構成や分類結果を確認してから本番データに適用してください。
同じ名前の写真がある場合の対処法
異なるカメラやスマートフォンから写真を取り込むと、同じファイル名の写真が存在することがあります。
例えば、次の2つです。
camera_a/IMG_0001.jpg
camera_b/IMG_0001.jpgこの記事の基本コードでは、同じ日付のフォルダに同名ファイルが存在する場合、上書きせずにスキップします。
そのため、すでにコピー先に存在する写真はそのまま残ります。
ただし、異なる写真が同じ名前だった場合、スキップされたファイルは自動では保存されません。必要に応じて、元のファイルを確認し、ファイル名に連番を付けるなどの対策を行いましょう。
対応していない画像形式やエラーへの対処法
基本編のコードでは、指定した拡張子の画像ファイルだけを処理します。
HEICなどの形式を整理したい場合は、対象形式を追加したうえで、その形式に対応する画像処理ライブラリなどを検討する必要があります。
また、次のようなエラーが発生する場合があります。
| エラー・問題 | 主な原因 | 対処法 |
|---|---|---|
| 写真フォルダが見つからない | フォルダ名やパスが違う | パスを確認する |
| PermissionError | ファイルへのアクセス権がない | 権限やファイルの使用状況を確認する |
| 写真が分類されない | 拡張子が対象外 | 拡張子の設定を確認する |
| 想定と異なる日付になる | 更新日時と撮影日時が異なる | EXIF情報を利用する |
| 同名ファイルがスキップされる | コピー先に同じ名前のファイルがある | 元ファイルを確認して対応する |
エラーが出た場合は、メッセージを確認し、フォルダパスやファイルの状態を順番にチェックしましょう。
Pythonによる写真整理の応用例
旅行ごとに写真を分類する
日付別の整理ができるようになったら、旅行ごとに写真を分類する方法にも応用できます。
例えば、次のようなフォルダ構成です。
travel_photos/
├── 2030_hokkaido/
├── 2030_kyoto/
└── 2030_okinawa/旅行ごとのフォルダに写真を保存しておけば、あとから旅行の記録を見返すときに便利です。
旅行先の情報を別途用意しておけば、撮影日と旅行期間を照合して分類する仕組みも作れます。
ただし、撮影日だけでは旅行先を自動判定できないため、旅行期間や旅行先のデータを用意する必要があります。
写真の一覧をCSVファイルに保存する
写真を整理するだけでなく、ファイル名や更新日時を一覧表にまとめることもできます。
CSVファイルに保存すれば、Excelなどの表計算ソフトで確認できます。
from pathlib import Path
from datetime import datetime
import csv
photo_folder = Path("photos")
csv_path = Path("photo_list.csv")
image_extensions = {
".jpg", ".jpeg", ".png",
".gif", ".bmp", ".webp", ".tif", ".tiff"
}
with csv_path.open(
"w",
newline="",
encoding="utf-8-sig"
) as csv_file:
writer = csv.writer(csv_file)
writer.writerow([
"ファイル名",
"更新日時",
"ファイルサイズ(バイト)"
])
for photo in sorted(photo_folder.iterdir()):
if not photo.is_file():
continue
if photo.suffix.lower() not in image_extensions:
continue
file_info = photo.stat()
modified_time = datetime.fromtimestamp(
file_info.st_mtime
)
writer.writerow([
photo.name,
modified_time.strftime("%Y-%m-%d %H:%M:%S"),
file_info.st_size
])
print(f"一覧を保存しました: {csv_path.resolve()}")このコードでは、写真のファイル名、更新日時、ファイルサイズをCSVに記録します。
encoding="utf-8-sig"を指定しているため、Windows版のExcelなどで日本語が文字化けする問題を軽減できます。
写真の一覧を作っておけば、写真がどこに保存されているかを確認したり、ファイルサイズを比較したりするときにも役立ちます。
なお、上記のコードは写真の一覧を作成するだけで、写真そのものの整理や移動は行いません。
大量の写真をまとめて整理する
写真が何千枚もある場合は、複数のフォルダをまとめて処理する機能を追加することもできます。
例えば、カメラやスマートフォンから取り込んだ写真が、複数のフォルダに分かれている場合です。
その場合は、Path.rglob()などを使って、サブフォルダ内の画像ファイルも検索できます。
ただし、コピー先のフォルダを検索対象に含めると、同じ写真を何度も処理してしまう可能性があります。
大量の写真を整理する場合は、整理元と整理先を明確に分け、テスト用データで動作を確認してから実行しましょう。
まとめ
この記事では、Pythonを使って写真を日付別フォルダに自動整理する方法を解説しました。
Pythonを使えば、写真のファイル情報を取得し、日付別のフォルダを自動で作成して、写真を整理できます。
今回紹介した内容を振り返ってみましょう。
- Pythonの標準ライブラリを使って写真を日付別に整理する
- ファイルの更新日時を取得してフォルダ名を作成する
- 元の写真を残しながらコピーする
- EXIF情報から実際の撮影日時を取得する
- 写真の一覧をCSVファイルに保存する
- テスト用フォルダを利用して安全に動作を確認する
最初は基本編のコードを実行し、少数の写真を日付別に分類するところから始めてみましょう。
慣れてきたら、撮影日時による分類やCSV出力などの機能を追加することで、自分に合った写真整理ツールを作れます。
旅行で撮影した写真や日常の記録を効率よく管理したい方は、ぜひPythonによる自動整理に挑戦してみてください。




