閉じる

Pythonでファイルの存在確認から安全な削除までを徹底解説

Pythonでファイルを扱う際には、存在確認や削除処理を誤ると、大事なデータを失ってしまう危険があります。

本記事では、Python標準ライブラリだけで「ファイルの存在確認」から「安全な削除」「本番運用の注意点」までを一通りマスターできるように、コード例と図解を交えながら丁寧に解説していきます。

Pythonでファイルの存在確認を行う方法

まずは、削除処理に入る前に欠かせない「ファイルの存在確認」について解説します。

存在しないファイルを削除しようとすると例外が発生してしまうため、削除処理の前段として、必ず存在確認を行う習慣を身につけることが重要です。

os.path.existsでファイルの存在確認を行う

最も基本的な存在確認の方法はos.path.existsを使うやり方です。

ファイルかディレクトリかを区別せず、「指定したパスに何かが存在するか」を真偽値で返してくれます。

os.path.existsの基本的な使い方

Python
import os

# 存在を確認したいパスを文字列で指定
path = "example.txt"

# os.path.existsは、ファイルまたはディレクトリが存在すればTrueを返します
if os.path.exists(path):
    print(f"{path} は存在します。")
else:
    print(f"{path} は存在しません。")
実行結果
example.txt は存在しません。

この例ではexample.txtというファイルパスを指定していますが、同じ関数でディレクトリの存在も確認できます

パスの種類を意識せずに、とりあえず何かあるかどうかを知りたい場合に便利です。

os.path.isfileとos.path.isdirの補足

os.path.existsは「何かがあればTrue」なので、ファイルとディレクトリを区別したい場合はos.path.isfileos.path.isdirを組み合わせると、より意図が明確になります。

この点は後述のis_file/is_dirと比較しながら見ていきます。

pathlib.Path.existsで直感的にファイルの有無を確認する

Python3ではpathlibモジュールが導入され、パスをオブジェクトとして扱えるようになりました。

最近のPythonコードでは、文字列ベースのos.pathよりpathlib.Pathを使う書き方が推奨されることが増えています

pathlibを使った存在確認の例

Python
from pathlib import Path

# Pathオブジェクトを生成します
path = Path("example.txt")

# existsメソッドで存在確認
if path.exists():
    print(f"{path} は存在します。")
else:
    print(f"{path} は存在しません。")
実行結果
example.txt は存在しません。

Pathオブジェクトに対してメソッドを呼び出すだけなので、読みやすく、メソッドチェーンで書き進めやすいのが利点です。

また、OSごとのパス区切り文字の違いも意識せずに扱える点が実務ではかなり便利です。

is_fileとis_dirでファイルとディレクトリを判別する

ファイル削除を行いたいのか、ディレクトリ削除を行いたいのかで、使う関数も大きく変わります。

Pathオブジェクトのis_fileis_dirを使うことで、対象がファイルかディレクトリかを簡単に見分けることができます。

is_fileとis_dirのサンプルコード

Python
from pathlib import Path

path = Path("data")

# ファイルかどうかを判定
if path.is_file():
    print(f"{path} はファイルです。")

# ディレクトリかどうかを判定
elif path.is_dir():
    print(f"{path} はディレクトリです。")

# どちらでもない場合(存在しない場合など)
else:
    print(f"{path} は存在しない、または通常のファイル/ディレクトリではありません。")
実行結果
data はディレクトリです。

削除処理の前には、この判定ロジックをはさんでおくことで、「ディレクトリに対してファイル削除関数を呼んでしまう」といった誤用を防げます。

ファイル存在確認時のパス指定と絶対パスの扱い

ファイルの存在確認で意外とトラブルになりやすいのが、相対パスと絶対パスの混在です。

スクリプトをどこから実行するかによって、相対パスの意味が変わってしまうためです。

現在の作業ディレクトリを確認する

Python
import os
from pathlib import Path

# osモジュールで現在の作業ディレクトリを取得
print("os.getcwd():", os.getcwd())

# pathlibで現在の作業ディレクトリを取得
print("Path.cwd():", Path.cwd())
実行結果
os.getcwd(): /home/user/project
Path.cwd(): /home/user/project

相対パスはこの「現在の作業ディレクトリ」からの相対位置として解釈されます。

思った場所を見ていない可能性がある場合は、print(os.getcwd())などで確認するとよいです。

絶対パスへ変換してから存在確認する方法

Python
from pathlib import Path

relative_path = Path("data/example.txt")

# resolveメソッドで絶対パスに変換(存在しないパスでも変換可能)
absolute_path = relative_path.resolve()

print("相対パス:", relative_path)
print("絶対パス:", absolute_path)
print("存在するか:", absolute_path.exists())
実行結果
相対パス: data/example.txt
絶対パス: /home/user/project/data/example.txt
存在するか: False

ログなどに絶対パスを記録しておくと、後から「どのファイルを扱ったのか」が明確になるため、安全な削除処理の一環としても有用です。

安全にファイルを削除する基本

ここからは、実際にファイルを削除する方法を解説していきます。

いきなり削除処理だけを書いてしまうと誤削除のリスクが高まりますので、「存在確認」→「削除」→「エラーハンドリング」という流れで理解することが重要です。

os.removeで単一ファイルを削除する手順

最も基本的なファイル削除関数はos.removeです。

指定したパスがファイルであれば削除を試み、存在しない場合や権限がない場合は例外を発生させます。

os.removeのシンプルな例

Python
import os

file_path = "example.txt"

# まずは存在確認を行うことが安全
if os.path.exists(file_path):
    # ファイルを削除します
    os.remove(file_path)
    print(f"{file_path} を削除しました。")
else:
    print(f"{file_path} は存在しません。削除は行いません。")
実行結果
example.txt は存在しません。削除は行いません。

このように存在確認を挟むことで、存在しないファイルに対してFileNotFoundErrorが発生するのを防げます

os.unlinkの使い方とos.removeとの違い

Pythonではos.removeos.unlinkの2つの関数がファイル削除に使えます。

実務的にはどちらを使ってもほぼ同じですが、由来と使い分けを知っておくとコードを読むときに迷いません。

os.unlinkの例と違いの解説

Python
import os

file_path = "example.txt"

if os.path.exists(file_path):
    # removeの代わりにunlinkを呼び出しても同様に削除されます
    os.unlink(file_path)
    print(f"{file_path} をunlinkで削除しました。")
else:
    print(f"{file_path} は存在しません。")
実行結果
example.txt は存在しません。

Unix系OSでは「unlink」というシステムコールを呼び出してファイルを削除します

Pythonのos.removeos.unlinkは、内部的にほぼ同じ仕組みを呼び出しており、仕様上も「同じ動作をする」と明記されています

そのため、どちらか一方に統一して使えば問題ありません。

削除前のファイル存在確認でエラーを防ぐ

削除しようとしたファイルが存在しない場合、os.removeos.unlinkFileNotFoundErrorを投げます。

存在確認を入れるだけで、このパターンのエラーは簡単に防ぐことができます。

pathlibと組み合わせた安全な削除関数

Python
from pathlib import Path

def safe_remove(path_str: str) -> None:
    """指定されたパスのファイルが存在する場合のみ削除する安全な関数"""
    path = Path(path_str)

    # ファイルであるかどうかまでチェックしてから削除する
    if path.is_file():
        path.unlink()  # Path.unlink() は os.unlink と同じ働きです
        print(f"{path} を削除しました。")
    elif path.exists():
        # ここに来るのは「ファイルではないが何かは存在する」ケース(ディレクトリなど)
        print(f"{path} はファイルではありません(削除しません)。")
    else:
        print(f"{path} は存在しません。")

# 実行例
safe_remove("example.txt")
実行結果
example.txt は存在しません。

このように存在確認と「ファイルかどうか」の確認を組み合わせることで、ディレクトリや特殊ファイルを誤って削除しようとするミスも防げます。

try exceptで削除時の例外をハンドリングする

存在確認をしていても、完全にエラーを防ぐことはできません。

例えば、存在確認と削除のあいだに別プロセスがファイルを削除してしまう可能性もあります。

このような「競合状態」を考えると、最後の砦としてtry/exceptで例外をきちんと処理することが重要になります。

代表的な例外をハンドリングするコード例

Python
import os

def remove_with_error_handling(path: str) -> None:
    """削除時に発生しうる代表的な例外をハンドリングする例"""
    try:
        os.remove(path)
        print(f"{path} を削除しました。")
    except FileNotFoundError:
        # ファイルがすでに存在しなかった場合
        print(f"{path} は存在しません(すでに削除された可能性があります)。")
    except PermissionError:
        # 権限が不足している場合(読み取り専用・他ユーザー所有など)
        print(f"{path} を削除する権限がありません。")
    except IsADirectoryError:
        # ディレクトリに対して remove を呼んだ場合
        print(f"{path} はディレクトリです。ファイル削除関数では削除できません。")
    except OSError as e:
        # その他のOSレベルのエラーを包括的にキャッチ
        print(f"予期しないエラーが発生しました: {e}")

# 実行例
remove_with_error_handling("example.txt")
実行結果
example.txt は存在しません(すでに削除された可能性があります)。

存在確認 + try/except の二段構えにすることで、削除処理はかなり堅牢になります。

ディレクトリや複数ファイルを安全に削除する

単一ファイルの削除が扱えるようになったら、次はディレクトリ削除や複数ファイル削除に進みます。

ここではshutilglobモジュールを用いた実践的なテクニックを見ていきます。

shutil.rmtreeでディレクトリを再帰的に削除する

ディレクトリとその中身をまとめて削除したい場合は、shutil.rmtreeを使うと一発で削除できます。

ただし、その強力さゆえ、パスを間違えると大量のファイルを一気に消してしまうリスクがあるため、慎重な扱いが必要です。

shutil.rmtreeの基本例

Python
import shutil
from pathlib import Path

dir_path = Path("old_logs")

if dir_path.exists() and dir_path.is_dir():
    # ディレクトリと中身を再帰的に削除します
    shutil.rmtree(dir_path)
    print(f"{dir_path} ディレクトリを再帰的に削除しました。")
else:
    print(f"{dir_path} は存在しないか、ディレクトリではありません。")
実行結果
old_logs は存在しないか、ディレクトリではありません。

本番環境では、rmtreeを呼ぶ前にログ出力や確認プロンプトを挟むことを強くおすすめします。

この点は後半の「ベストプラクティス」で詳しく触れます。

globでパターン指定し複数ファイルを削除する

ログファイルや一時ファイルなど、特定のパターンにマッチする複数ファイルを一括削除したい場面ではglobモジュールが非常に便利です。

globでマッチしたファイルを一括削除

Python
import glob
import os

def remove_logs(pattern: str) -> None:
    """globパターンにマッチするファイルを一括削除する例"""
    # パターンにマッチするパス一覧を取得
    for path in glob.glob(pattern):
        # 念のためファイルかどうかを確認
        if os.path.isfile(path):
            os.remove(path)
            print(f"{path} を削除しました。")
        else:
            print(f"{path} はファイルではないため削除しません。")

# 実行例: カレントディレクトリ内の *.log ファイルを削除
remove_logs("*.log")
実行結果
app.log を削除しました。
error.log を削除しました。

パターンが広すぎると想定以上のファイルが消えるため、まずは削除せずにprintだけ行って、対象を確認する段階を挟むと安全です。

read onlyファイルや権限エラーへの対処方法

削除処理では、ファイルが読み取り専用になっていたり、ユーザー権限が不足していたりするとPermissionErrorが発生します。

PermissionErrorをキャッチしてメッセージを出す例

Python
import os
import stat

def safe_remove_with_permission_check(path: str) -> None:
    """読み取り専用ファイルへの対処の雰囲気を示す例"""
    try:
        os.remove(path)
        print(f"{path} を削除しました。")
    except PermissionError:
        print(f"{path} を削除できません(PermissionError)。読み取り専用の可能性があります。")
        # 必要であれば、以下のように権限を変更して再試行することもあります
        try:
            # 書き込み権限を付与(所有者に書き込み権限を追加)
            os.chmod(path, stat.S_IWRITE)
            os.remove(path)
            print(f"権限を変更して {path} を削除しました。")
        except Exception as e:
            print(f"権限変更後も削除に失敗しました: {e}")

# 実行例
safe_remove_with_permission_check("read_only.txt")
実行結果
read_only.txt を削除できません(PermissionError)。読み取り専用の可能性があります。
権限変更後も削除に失敗しました: [Errno 2] No such file or directory: 'read_only.txt'

実際の本番環境では、権限を強制的に変更して削除することが常に正しいとは限りません

運用ルールに従い、ログを残して管理者に通知するなど、組織のポリシーに合わせた対処が必要です。

ごみ箱へ移動して安全に削除する方法

本当に削除してしまうのが不安な場合、一旦ごみ箱に移動してから手動で完全削除する方法があります。

Python標準ライブラリではありませんが、send2trashというサードパーティライブラリを使うと簡単に実現できます。

send2trashを使ったごみ箱への移動例

まず、事前にインストールします。

Shell
pip install send2trash
実行結果
Collecting send2trash
Installing collected packages: send2trash
Successfully installed send2trash-1.8.2

続いて、Pythonコード側で利用します。

Python
from send2trash import send2trash
from pathlib import Path

def move_to_trash(path_str: str) -> None:
    """ファイルを即削除せず、ごみ箱に移動する関数"""
    path = Path(path_str)

    if not path.exists():
        print(f"{path} は存在しません。")
        return

    # 実際には削除せず、ごみ箱に移動します
    send2trash(path)
    print(f"{path} をごみ箱に移動しました。")

# 実行例
move_to_trash("important.txt")
実行結果
important.txt をごみ箱に移動しました。

誤削除が致命的な環境では「まずはごみ箱へ」が強力な安全策になります。

安全なファイル削除のベストプラクティス

ここまでで、存在確認から各種削除手法まで一通り見てきました。

最後に、実際の運用で誤削除を防ぎ、安全にスクリプトを回すためのベストプラクティスを整理します。

誤削除を防ぐための確認プロンプトの実装

自動化されたスクリプトであっても、危険度が高い削除処理の前には、人間の最終確認を挟むと安全性が大きく向上します。

確認プロンプト付き削除スクリプト

Python
from pathlib import Path

def confirm_and_delete(path_str: str) -> None:
    """ユーザーに確認してから削除する安全な関数"""
    path = Path(path_str).resolve()

    if not path.exists():
        print(f"{path} は存在しません。")
        return

    print(f"削除対象: {path}")
    answer = input("本当に削除しますか?(y/N): ").strip().lower()

    # デフォルトは「削除しない」
    if answer == "y":
        if path.is_file():
            path.unlink()
            print("ファイルを削除しました。")
        elif path.is_dir():
            # ディレクトリ削除はさらに慎重に
            print("これはディレクトリです。別の関数で削除してください。")
        else:
            print("通常のファイル/ディレクトリではないため削除しません。")
    else:
        print("削除をキャンセルしました。")

# 実行例(対話形式のため実行結果は環境に依存します)
実行結果
削除対象: /home/user/project/example.txt
本当に削除しますか?(y/N): n
削除をキャンセルしました。

デフォルトを「削除しない(N)」にしておくことが重要なポイントです。

ログ出力で削除処理を記録する方法

削除処理は、後から「何をいつ削除したのか」を追跡できるようにしておくことが重要です。

Pythonのloggingモジュールを使うと、標準出力だけでなくログファイルにも簡単に記録できます。

loggingモジュールを使った削除ログ

Python
import logging
from pathlib import Path

# ログの基本設定(ファイル出力)
logging.basicConfig(
    filename="deletion.log",
    level=logging.INFO,
    format="%(asctime)s [%(levelname)s] %(message)s",
)

logger = logging.getLogger(__name__)

def logged_delete(path_str: str) -> None:
    """削除処理をログに記録する例"""
    path = Path(path_str).resolve()

    if not path.exists():
        msg = f"{path} は存在しません。"
        print(msg)
        logger.warning(msg)
        return

    if path.is_file():
        try:
            path.unlink()
            msg = f"ファイル削除: {path}"
            print(msg)
            logger.info(msg)
        except Exception as e:
            msg = f"ファイル削除失敗: {path} error={e}"
            print(msg)
            logger.error(msg)
    else:
        msg = f"{path} はファイルではないため、削除対象外です。"
        print(msg)
        logger.warning(msg)

# 実行例
logged_delete("example.txt")
実行結果
/home/user/project/example.txt は存在しません。
実行結果
# deletion.log の例(抜粋)
2025-12-19 10:00:00,123 [WARNING] /home/user/project/example.txt は存在しません。

ログは誤削除が疑われたときの「証跡」として非常に重要です。

テンポラリファイルの安全な作成と削除

処理の途中で一時的に必要になるファイルは、専用のテンポラリ領域に安全に作成し、処理後に確実に削除するのが望ましいです。

Pythonにはtempfileモジュールが用意されています。

tempfile.NamedTemporaryFileの例

Python
import tempfile
from pathlib import Path

def use_temp_file() -> None:
    """一時ファイルを使って処理を行い、最後に削除する例"""
    # delete=True の場合、ファイルはクローズ時に自動削除されます
    with tempfile.NamedTemporaryFile(mode="w+", delete=True, suffix=".txt") as tmp:
        print(f"作成された一時ファイル: {tmp.name}")

        # 一時ファイルにデータを書き込み
        tmp.write("一時的なデータです。\n")
        tmp.flush()

        # 必要ならここで別処理が tmp.name を使って読み取り可能
        path = Path(tmp.name)
        print(f"一時ファイルは存在しますか? {path.exists()}")

    # withブロックを抜けると自動的に削除されます
    print(f"ブロック終了後、一時ファイルは存在しますか? {Path(tmp.name).exists()}")

# 実行例
use_temp_file()
実行結果
作成された一時ファイル: /tmp/tmpabcd1234.txt
一時ファイルは存在しますか? True
ブロック終了後、一時ファイルは存在しますか? False

tempfileを使うことで、名前衝突や権限周りのリスクを自分で気にせずに済むため、安全性と生産性が同時に高まります。

本番環境でのファイル削除スクリプト運用のポイント

最後に、本番環境で削除スクリプトを運用する際に意識したいポイントを整理します。

ここでは文章でまとめますが、実際にはプロジェクトごとの運用ルールに落とし込むことが重要です。

まず権限の絞り込みが大切です。

削除スクリプトを実行できるユーザーやサービスアカウントを限定し、実行可能な範囲を最小限に抑えます。

また、対象ディレクトリもあらかじめ限定し、それ以外へは削除を行わないようガードを設けると安全です。

次にdry-run(試し実行)モードの用意が有効です。

本当に削除する前に、「どのファイルが削除対象になるか」だけを一覧表示するモードを実装しておくと、設定ミスやパターンミスに早く気づけます。

例えば、引数や設定ファイルでdry_run=Trueのときはos.removeを呼ばずにprintだけにする、といった形です。

さらにバックアップとロールバック戦略も重要です。

定期削除の対象となるファイルであっても、一定期間はバックアップを保持しておくことで、誤削除時に復旧できる可能性が高まります。

削除スクリプトの実行前後にスナップショットを取る運用も考えられます。

最後にテスト環境で十分に検証することを忘れてはいけません。

本番と同等のディレクトリ構成とテストデータを用意し、ログやdry-runの結果を確認しながら、想定どおりのファイルだけが対象になっているかを慎重に確認します。

ここまで徹底してはじめて、本番環境に安心して投入できると言えます。

まとめ

Pythonではos.pathやpathlibによる存在確認から、os.remove/unlinkやshutil.rmtreeによる削除globを使った一括削除send2trashによるごみ箱移動まで、多彩な手段でファイル操作を行えます。

しかし、重要なのは「どう削除するか」だけでなく、誤削除を防ぐための存在確認・権限チェック・ログ記録・確認プロンプト・dry-run・バックアップといった安全策を組み合わせることです。

本記事で紹介したベストプラクティスを参考に、安心して運用できるファイル削除スクリプトを構築してみてください。

クラウドSSLサイトシールは安心の証です。

URLをコピーしました!