Pythonで毎日の作業を自動化する入門|ダウンロードフォルダを自動で整理しよう

パソコンの「ダウンロード」フォルダ、こんな状態になっていませんか?

  • 「請求書のPDF、資料のExcel、スクショの画像が全部ごちゃまぜで、探すのに毎回時間がかかる」
  • 「同じファイルを何度もダウンロードして、資料(1).pdf 資料(2).pdf が増えていく」
  • 「月末にまとめて片付けようと思って、結局そのまま」

こういう「毎日少しずつ発生して、やり方が毎回同じ」作業は、Pythonに任せるのにぴったりです。

今回は、Pythonをほとんど触ったことがない方でも、ダウンロードフォルダを「種類別・月別」に自動で整理するスクリプトを1本完成させるところまで進めます。

拡張子ごとのフォルダと月フォルダに、Pythonが毎日自動で振り分けます。

💡
この記事でわかること
  • 自動化する作業の選び方(「回数 × 時間」と「ルールが決まっているか」)
  • Pythonの準備(インストールの確認とVS Code)
  • ダウンロードフォルダを整理するスクリプトと、その読み方
  • いきなりファイルを動かさない「確認モード」の使い方
  • 毎日自動で動かす設定(Windows・Mac)
  • よくあるエラーと直し方

なぜ「毎日の作業」を自動化するのか

1回あたり数分の作業でも、毎日続けば積み重なります。

たとえば、ダウンロードしたファイルを探したり片付けたりする時間が1日3分だとすると、平日だけでも1か月で約1時間です。

しかも、手作業には次のような弱点があります。

  • 疲れている日は後回しにして、結局たまっていく
  • どこに置いたか、人によって(その日の気分によって)ルールがぶれる
  • 間違えて大事なファイルを消してしまうことがある

ルールをコードにしておけば、毎日同じ基準で、文句を言わずに片付けてくれます。

浮いた時間は、副業の作業や学習にそのまま使えます。


自動化する作業の選び方:「回数 × 時間」と「ルールが決まっているか」

最初の1本で大事なのは、小さくて、効果がわかりやすい作業を選ぶことです。

次の2つの軸で考えると、選びやすくなります。

  1. 回数 × 時間:どれくらいの頻度で、1回に何分かかっているか
  2. ルールが決まっているか:「PDFならここ」「画像ならここ」のように、判断に迷わないか

回数が多くてルールが決まっている作業から自動化するのがおすすめです。

作業の例 回数 × 時間 ルール 最初の1本に向いているか
ダウンロードフォルダの整理 毎日 × 数分 拡張子で決まる ◎ 向いている
写真ファイルの名前を日付に変える 週1回 × 10分 日付で決まる ○ 向いている
取引先へのメール返信 毎日 × 30分 毎回判断が必要 × 向いていない

「毎回判断が必要な作業」は、無理に自動化しなくて大丈夫です。

まずはルールがはっきりしていて、失敗しても取り返しがつく作業から始めましょう。

自分の副業や作業の中から候補を探したい方は、こちらのチェックリストも参考になります。

自動化できる副業の選び方チェックリスト

また、「その作業はPythonでやるべき?GASやn8nのほうがいい?」と迷ったら、こちらで使い分けをまとめています。

自動化スタック総覧|GAS・n8n・Python・Notionの使い分け


今回作るもの:ダウンロードフォルダの自動整理

今回のスクリプトは、ダウンロードフォルダにあるファイルを、次のように振り分けます。

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
Downloads/
└── _整理済み/
    ├── PDF/
    │   └── 2026-10/
    │       └── 請求書.pdf
    ├── 画像/
    │   └── 2026-10/
    │       └── screenshot.png
    ├── 表計算/
    ├── 文書/
    └── その他/

ルールは次のとおりです。

  • 種類:拡張子(.pdf や .png など)で振り分ける
  • 月:ファイルの更新日時で「2026-10」のような月別フォルダに分ける
  • 安全のために触らないもの:フォルダ、隠しファイル、ダウンロード途中のファイル、10分以内に更新されたファイル
  • 同じ名前のファイルがあるとき:上書きせず、report_1.pdf のように番号を付ける

このスクリプトはファイルを削除しません。動かすだけなので、気に入らなければ手で元に戻せます。


準備:Pythonのインストール確認とVS Code

1. Pythonが入っているか確認する

Windowsは「PowerShell」、Macは「ターミナル」を開いて、次のコマンドを入力します。

  • 1
  • 2
  • 3
  • 4
  • 5
# Windows
py --version

# Mac
python3 --version

Python 3.12.4 のように「Python 3.」から始まる番号が表示されればOKです。

表示されない場合は、公式サイトからインストールします。

  • Windows:python.org からインストーラーをダウンロード。最初の画面で「Add python.exe to PATH」にチェックを入れてからインストールします
  • Mac:python.org からインストーラーをダウンロードするのが簡単です。python3 を実行したときに「コマンドライン・デベロッパ・ツール」のインストールを求められた場合は、それに従ってもOKです

2. VS Codeを用意する

コードを書くエディタは、無料のVisual Studio Code(VS Code)がおすすめです。

インストールしたら、左側の「拡張機能」から「Python」(Microsoft製)を入れておくと、色分けやエラー表示が見やすくなります。

3. 作業用のフォルダを作る

スクリプトを置くフォルダを1つ作ります。ここでは例として、ホームフォルダに scripts というフォルダを作ります。

  • Windows:C:\Users\あなたのユーザー名\scripts
  • Mac:/Users/あなたのユーザー名/scripts

VS Codeで「フォルダーを開く」からこのフォルダを開き、organize_downloads.py という名前で新しいファイルを作ります。

📝
仮想環境(venv)は今回なくてもOK

今回のスクリプトは、Pythonに最初から入っている機能(標準ライブラリ)だけで動きます。pip install も不要です。外部のライブラリを使うようになったら、仮想環境を作ると管理しやすくなります。


スクリプト全文

次のコードを、そのまま organize_downloads.py に貼り付けて保存してください。

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
"""ダウンロードフォルダを「種類別・月別」に自動で整理するスクリプト

使い方:
    python organize_downloads.py          # 確認だけ(ファイルは動かさない)
    python organize_downloads.py --run    # 実際に移動する
"""

import argparse
import shutil
from datetime import datetime, timedelta
from pathlib import Path

# ===== 設定(自分の環境に合わせて変更) =====
TARGET_DIR = Path.home() / "Downloads"   # 整理したいフォルダ
DEST_DIR = TARGET_DIR / "_整理済み"        # 整理先のフォルダ

# 拡張子 → 振り分け先フォルダ名
CATEGORIES = {
    "画像": [".jpg", ".jpeg", ".png", ".gif", ".webp", ".heic", ".svg"],
    "PDF": [".pdf"],
    "文書": [".doc", ".docx", ".txt", ".md", ".ppt", ".pptx"],
    "表計算": [".xls", ".xlsx", ".csv"],
    "圧縮ファイル": [".zip", ".7z", ".rar", ".tar", ".gz"],
    "インストーラー": [".exe", ".msi", ".dmg", ".pkg"],
    "動画・音声": [".mp4", ".mov", ".mp3", ".wav", ".m4a"],
}
OTHER = "その他"

# ダウンロード途中のファイルは触らない
SKIP_SUFFIXES = {".crdownload", ".part", ".download", ".tmp"}
# 更新されてから10分以内のファイルも触らない(使用中かもしれないため)
SKIP_RECENT = timedelta(minutes=10)
# ==========================================


def get_category(path: Path) -> str:
    """拡張子から振り分け先のフォルダ名を決める"""
    suffix = path.suffix.lower()
    for category, suffixes in CATEGORIES.items():
        if suffix in suffixes:
            return category
    return OTHER


def unique_path(path: Path) -> Path:
    """同じ名前のファイルがあれば「名前_1.拡張子」のように番号を付ける"""
    if not path.exists():
        return path
    i = 1
    while True:
        candidate = path.with_name(f"{path.stem}_{i}{path.suffix}")
        if not candidate.exists():
            return candidate
        i += 1


def organize(run: bool) -> None:
    if not TARGET_DIR.is_dir():
        print(f"フォルダが見つかりません:{TARGET_DIR}")
        return

    now = datetime.now()
    moved = skipped = 0

    for path in sorted(TARGET_DIR.iterdir()):
        # フォルダ・隠しファイル・ダウンロード途中のファイルは対象外
        if not path.is_file() or path.name.startswith("."):
            continue
        if path.suffix.lower() in SKIP_SUFFIXES:
            skipped += 1
            continue

        modified = datetime.fromtimestamp(path.stat().st_mtime)
        if now - modified < SKIP_RECENT:
            skipped += 1
            continue

        # 例:_整理済み/画像/2026-10/photo.png
        dest_folder = DEST_DIR / get_category(path) / modified.strftime("%Y-%m")
        dest = unique_path(dest_folder / path.name)

        if run:
            dest_folder.mkdir(parents=True, exist_ok=True)
            shutil.move(str(path), str(dest))
            print(f"移動しました:{path.name} -> {dest.relative_to(TARGET_DIR)}")
        else:
            print(f"[確認] {path.name} -> {dest.relative_to(TARGET_DIR)}")
        moved += 1

    label = "移動" if run else "移動予定"
    print(f"--- {label}:{moved}件 / スキップ:{skipped}件 ---")
    if not run:
        print("※確認モードです。実際に移動するには --run を付けて実行してください。")


def main() -> None:
    parser = argparse.ArgumentParser(description="ダウンロードフォルダを整理します")
    parser.add_argument("--run", action="store_true", help="実際にファイルを移動する")
    args = parser.parse_args()
    organize(run=args.run)


if __name__ == "__main__":
    main()

コードを上から順に読んでみよう

全部を一度に理解しなくて大丈夫です。「どこを変えれば自分用になるか」がわかれば十分です。

① 設定のブロック
  • 1
  • 2
TARGET_DIR = Path.home() / "Downloads"   # 整理したいフォルダ
DEST_DIR = TARGET_DIR / "_整理済み"        # 整理先のフォルダ

Path.home() は、自分のホームフォルダ(C:\Users\名前 や /Users/名前)を表します。そこに / "Downloads" をつなげて、ダウンロードフォルダを指定しています。

pathlib の Path を使うと、WindowsでもMacでも同じ書き方でフォルダを指定できます。

その下の CATEGORIES は、「どの拡張子を、どのフォルダに入れるか」の対応表です。よく使う拡張子があれば、ここに追加するだけで振り分け先を増やせます。

② 触らないファイルを決める
  • 1
  • 2
SKIP_SUFFIXES = {".crdownload", ".part", ".download", ".tmp"}
SKIP_RECENT = timedelta(minutes=10)

.crdownload(Chrome)や .part(Firefox)などは、ダウンロード途中のファイルです。これを動かすとダウンロードが失敗するので、対象から外しています。

また、更新されてから10分以内のファイルは「今まさに使っているかもしれない」ので、次回に回します。

③ 振り分け先を決める関数 get_category

ファイルの拡張子を小文字にそろえて(.JPG も .jpg として扱うため)、対応表から振り分け先を探します。見つからなければ「その他」です。

④ 上書きを防ぐ関数 unique_path

移動先に同じ名前のファイルがすでにあれば、report_1.pdf、report_2.pdf…と空いている名前を探します。大事なファイルを上書きで消してしまう事故を防ぐための部分です。

⑤ 本体の関数 organize

ダウンロードフォルダの中身を1つずつ見ていき、次の順番で処理します。

  1. フォルダ・隠しファイル・ダウンロード途中のファイルなら、飛ばす
  2. 更新日時を調べて、10分以内なら飛ばす
  3. 「種類」と「月」から移動先を決める
  4. 確認モードなら表示だけ、--run 付きなら実際に移動する

実際の移動は shutil.move が担当しています。移動先のフォルダがなければ mkdir(parents=True, exist_ok=True) で自動的に作ります。

⑥ 起動部分

最後の argparse の部分で、--run が付いているかどうかを受け取っています。

if __name__ == "__main__": の意味が気になった方は、こちらで詳しく解説しています。

Pythonの「おまじない」って何?「if name == "main"」の正体と意味をやさしく解説!


安全第一:まず「確認モード」で動かす

ファイルを動かすスクリプトは、いきなり本番のフォルダで実行しないのが鉄則です。次の3段階で試しましょう。

練習用フォルダで試し、確認モードでチェックしてから --run で実行します。

ステップ1:練習用のフォルダで試す

デスクトップに test_downloads というフォルダを作り、いらないファイルをいくつかコピーしておきます。

そのうえで、設定の1行を一時的に書き換えます。

  • 1
TARGET_DIR = Path.home() / "Desktop" / "test_downloads"

ターミナル(PowerShell)でスクリプトを置いたフォルダに移動し、まずは何も付けずに実行します。

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
# スクリプトを置いたフォルダに移動
cd ~/scripts

# Windows
py organize_downloads.py

# Mac
python3 organize_downloads.py

何も付けずに実行したときは「確認モード」なので、ファイルは1つも動きません。どこに移動する予定かが表示されるだけです。

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
[確認] Photo2.JPG -> _整理済み/画像/2026-09/Photo2.JPG
[確認] backup.zip -> _整理済み/圧縮ファイル/2026-10/backup.zip
[確認] memo.txt -> _整理済み/文書/2026-09/memo.txt
[確認] report.pdf -> _整理済み/PDF/2026-09/report.pdf
[確認] sales.csv -> _整理済み/表計算/2026-10/sales.csv
[確認] unknown.xyz -> _整理済み/その他/2026-10/unknown.xyz
--- 移動予定:6件 / スキップ:2件 ---
※確認モードです。実際に移動するには --run を付けて実行してください。

表示を見て、振り分け先が思ったとおりなら、--run を付けて実行します。

  • 1
  • 2
  • 3
  • 4
  • 5
# Windows
py organize_downloads.py --run

# Mac
python3 organize_downloads.py --run

  • 1
  • 2
  • 3
  • 4
移動しました:Photo2.JPG -> _整理済み/画像/2026-09/Photo2.JPG
移動しました:backup.zip -> _整理済み/圧縮ファイル/2026-10/backup.zip
...
--- 移動:6件 / スキップ:2件 ---

練習用フォルダの中に _整理済み フォルダができて、ファイルが振り分けられていれば成功です。もう一度実行すると「移動:0件」になり、何度実行しても同じファイルを二重に動かさないことも確認できます。

ステップ2:確認モードで本番のフォルダをチェックする

うまくいったら、TARGET_DIR を元の Path.home() / "Downloads" に戻します。

本番のダウンロードフォルダでも、まずは何も付けずに(確認モードで)実行して、移動予定の一覧を確認します。この時点では、まだファイルは1つも動きません。

  • 1
  • 2
  • 3
  • 4
  • 5
# Windows
py organize_downloads.py

# Mac
python3 organize_downloads.py

表示された一覧を見ながら、次の3点をチェックしましょう。

⚠️
実行前にここだけチェック
確認モードの表示に、動かしたくないファイルが含まれていない
大事なファイルは、念のため別の場所にバックアップしてある
振り分け先のフォルダ名が、自分にとってわかりやすい

ステップ3:--run を付けて本番で実行する

チェックがすべてOKなら、--run を付けて実行します。

  • 1
  • 2
  • 3
  • 4
  • 5
# Windows
py organize_downloads.py --run

# Mac
python3 organize_downloads.py --run

ダウンロードフォルダの中に _整理済み フォルダができ、ファイルが種類別・月別に振り分けられていれば完成です。

このスクリプトはファイルを削除せず、同じ名前のファイルがあっても上書きしないので、思っていた場所と違うファイルがあれば _整理済み から手で戻せます。


毎日自動で動かす:Windowsのタスクスケジューラ・Macのcron/launchd

手で実行して問題なければ、毎日決まった時間に動くように設定します。

どの方法でも、Pythonとスクリプトはフルパス(省略しない場所の書き方)で指定するのがポイントです。

Pythonのフルパスは、次のコマンドで調べられます。

  • 1
  • 2
  • 3
  • 4
  • 5
# Windows
py -c "import sys; print(sys.executable)"

# Mac
python3 -c "import sys; print(sys.executable)"

Windows:タスクスケジューラ
  1. スタートメニューで「タスクスケジューラ」を検索して開く
  2. 右側の「基本タスクの作成」をクリックし、名前(例:ダウンロード整理)を付ける
  3. トリガー:「毎日」を選び、時刻を設定(例:12:00)
  4. 操作:「プログラムの開始」を選ぶ
  5. プログラム/スクリプト:上で調べた python.exe のフルパス
  6. 引数の追加:C:\Users\あなたのユーザー名\scripts\organize_downloads.py --run
  7. 完了後、作成したタスクを右クリック →「実行する」で、1回テストしておく

パソコンの電源が切れていて実行できなかった日のために、タスクのプロパティの「設定」タブで「スケジュールされた時刻にタスクを開始できなかった場合、すぐにタスクを実行する」にチェックを入れておくと安心です。

Mac:cron(いちばん手軽)

ターミナルで crontab -e を実行し、次の1行を追加して保存します。

  • 1
  • 2
# 毎日12:00に実行し、結果をログファイルに残す
0 12 * * * /usr/bin/python3 /Users/yourname/scripts/organize_downloads.py --run >> /Users/yourname/scripts/organize.log 2>&1

/usr/bin/python3 と /Users/yourname の部分は、自分の環境に置き換えてください。

cronは、指定した時刻にMacがスリープしていると、その日は実行されません。

Mac:launchd(スリープ明けにも実行したい場合)

Mac標準の仕組みであるlaunchdを使うと、指定時刻にスリープしていた場合でも、復帰したあとに実行してくれます。

~/Library/LaunchAgents/com.example.organize-downloads.plist というファイルを作り、次の内容を書きます。

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.example.organize-downloads</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/bin/python3</string>
        <string>/Users/yourname/scripts/organize_downloads.py</string>
        <string>--run</string>
    </array>
    <key>StartCalendarInterval</key>
    <dict>
        <key>Hour</key>
        <integer>12</integer>
        <key>Minute</key>
        <integer>0</integer>
    </dict>
    <key>StandardOutPath</key>
    <string>/Users/yourname/scripts/organize.log</string>
    <key>StandardErrorPath</key>
    <string>/Users/yourname/scripts/organize.log</string>
</dict>
</plist>

保存したら、ターミナルで読み込みます。

  • 1
launchctl load ~/Library/LaunchAgents/com.example.organize-downloads.plist

止めたいときは launchctl unload に変えて同じコマンドを実行します。


よくあるエラーと直し方

症状 よくある原因 直し方
Windowsで python と打つとMicrosoft Storeが開く/「認識されません」と出る PATHが通っていない py コマンドを使う。またはインストーラーで「Add python.exe to PATH」にチェックして入れ直す
can't open file ... No such file or directory スクリプトがあるフォルダに移動していない cd でフォルダに移動するか、スクリプトをフルパスで指定する
SyntaxError: invalid syntax(コマンドを打ったとき) >>> が出ている「Pythonの対話モード」の中でコマンドを打っている exit() で対話モードを抜けてから、ターミナルで実行する
「フォルダが見つかりません」と表示される TARGET_DIR の場所が違う 日本語環境では「ダウンロード」と表示されていても、実際のフォルダ名は Downloads です。エクスプローラーやFinderで実際の場所を確認する
PermissionError が出る ファイルを別のアプリで開いている アプリを閉じてから再実行する
Macの定期実行で Operation not permitted がログに出る macOSのプライバシー設定で、ダウンロードフォルダへのアクセスが許可されていない 「システム設定」→「プライバシーとセキュリティ」→「フルディスクアクセス」で、cron(/usr/sbin/cron)や使っているPythonを許可する
手動では動くのに、定期実行だと動かない パスを省略している Pythonとスクリプトをフルパスで指定し、ログを見て原因を確認する

次のステップ:自分用にアレンジしてみよう

1本動いたら、少しずつ自分用に育てていきましょう。

  • 振り分けルールを増やす:CATEGORIES に、よく使う拡張子を追加する
  • 対象のフォルダを変える:TARGET_DIR をデスクトップにすれば、デスクトップの片付けにも使える
  • 古いファイルだけを動かす:SKIP_RECENT を timedelta(days=7) にすれば、「1週間たったファイルだけ整理」になる

ファイル整理に慣れてきたら、次は「中身を処理する」自動化にも挑戦してみてください。

📚
もっと学びたい人へ

biliotechのメンバーが書いたPythonのKindle本を、悩み別にまとめています。スクリプトの処理が遅く感じてきたら、こちらものぞいてみてください。

biliotechまわりのKindle著書リスト


まとめ

今回は、Pythonの標準ライブラリだけで、ダウンロードフォルダを自動で整理するスクリプトを作りました。

  • 自動化する作業は「回数 × 時間」と「ルールが決まっているか」で選ぶ
  • ファイルを動かすスクリプトは、練習用フォルダと確認モードで試してから本番へ
  • 定期実行は、Pythonとスクリプトをフルパスで指定する

次の一歩は、練習用フォルダを作って、確認モードで1回動かしてみることです。表示された振り分け結果を眺めるだけでも、「自分の作業がコードに置き換わる」感覚がつかめるはずです。


メンバーのSNSアカウントはこちら

◆かいと:IT担当
X(旧Twitter)
Instagram