Python pathlibで.tar.gzを判定する:suffixとsuffixesの違い

プログラミング・Web開発カテゴリを表すパンダのイラスト プログラミング・Web開発

この記事について この記事は、生成AIを活用した自動生成フローで作成しています。Python公式ドキュメントに基づき、架空のファイル名で拡張子の読み方を比較します。

検証ステータス:📘 公式仕様確認・掲載コードの実機実行は未確認

Python pathlibで.tar.gzを判定する:suffixとsuffixesの違い

「拡張子を調べたのに.gzしか出ない」のはなぜ?

受け取ったバックアップの名前が backup.tar.gz だったとします。拡張子を見れば「tarでまとめたデータをgzipで圧縮したもの」と判断したくなります。しかしPythonの Path.suffix を使うと、返るのは .gz だけです。「tarが消えた」「Pythonが圧縮形式を誤認した」と考える前に、そもそも何を取り出す機能なのか整理しましょう。

結論は、suffix が返すのは最後の拡張子部分、suffixes は拡張子部分をリストとして返す、という違いです。ただし、複数のドットを含む名前がすべて複合圧縮形式という意味ではありません。名前を読む処理と、実際のファイル形式を検証する処理は別物です。ここを混同すると、誤った分類や危険な自動展開につながります。 実在するバックアップや機密ファイルを使わず、文字列だけで判定を試します。最後には拡張子が期待どおりでも中身の安全性は保証されない理由を、業務の受入チェックに結び付けます。

対象環境と準備

項目内容
言語Python 3系、標準ライブラリ pathlib
操作ファイル名の文字列を解析するだけ
権限管理者権限不要
書込みなし。ファイルを開かず、展開もしない
検証範囲公式仕様を参照。掲載コードは実機未実行

Path はファイルシステム上のパスを扱うクラスですが、ここでは PurePath を使います。PurePath はパス文字列の構造を扱い、対象ファイルが存在しなくても利用できます。練習ではファイルを作る必要すらありません。実際のOS上の存在確認やアクセス権とは切り離せるため、初学者が安全に違いを観察するのに向いています。

最初の実験:同じ名前を2通りで読む

次のコードをPython 3の対話環境または手元の練習用スクリプトで試してください。期待結果は公式仕様に基づく予想であり、この制作工程での実行結果ではありません。

from pathlib import PurePath

name = PurePath("backup.tar.gz")
print(name.suffix)
print(name.suffixes)

期待される表示は1行目が .gz、2行目が ['.tar', '.gz'] です。前者は単一の文字列、後者は複数の文字列を持つリストです。重要なのは、suffixes が「tarとgzipを解析して検出した」のではない点です。名前にあるドットの区切りを返しているだけで、ファイルの先頭バイトや圧縮方式を読み取っていません。

たとえば受信したファイル名が report.final.csv なら、suffix は .csv、suffixes は ['.final', '.csv'] になります。.final は作業上の版名かもしれず、データ形式を表すとは限りません。ここで「複数拡張子だから二重圧縮」と決めつけると、正常な報告書まで誤分類してしまいます。

図で理解する:末尾だけ取るか、並べて取るか

下の図は同じファイル名から2種類の情報を取り出す流れを表しています。分岐の先で返り値の形も異なる点に注目してください。

flowchart TD
    A["backup.tar.gz という名前"] --> B{"どの属性を読む?"}
    B -->|suffix| C["最後の部分 .gz"]
    B -->|suffixes| D["リスト .tar と .gz"]
    C --> E["名前の末尾の手掛かり"]
    D --> E
    E --> F["中身の形式は未検証"]

図の最後が「中身の形式は未検証」になっていることがポイントです。どちらの属性もファイル名の情報です。受信データを本当に解凍できるか、改ざんされていないか、内部に不審なパスがないかまでは調べません。形式判定を拡張子だけに任せる設計は、便利でも限界があります。

条件を変える:ドットが増えたらどうなる?

今度は複数の名前を一度に並べて比較します。ファイルを生成するのではなく、リスト内の文字列を順番に読むだけです。表示の違いを見ながら、名前に含まれるドットの意味を考えてみてください。

from pathlib import PurePath

names = ["backup.tar.gz", "report.final.csv", "archive.zip", "README"]
for value in names:
    p = PurePath(value)
    print(value, "=>", p.suffix, p.suffixes)

archive.zip は最後の .zip だけを持ち、README のようにドットがない名前では空文字列と空リストが期待されます。拡張子がないことは、必ずしも中身がテキストであることを意味しません。逆に .zip と名付けたからといって、実体がZIP形式になるわけでもありません。

ここで発見したいのは「名前の規則」と「データの実体」を分けることです。たとえば report.final.csv の .final は人が付けた状態表示です。機械が全てのドットを形式の区切りとして解釈すると、実際の業務上の命名規則と衝突します。複合拡張子の一覧は、ファイル形式を確定する証拠ではなく、分類に使う候補情報です。

.tar.gzだけを候補として扱うには

複合形式を受け入れる業務では、suffixes の最後の2要素を確認する方法が考えられます。ただし「末尾が一致したら即展開」にはしません。まず名前の段階で候補を絞り、別工程でファイル形式や受信元を検証する設計にします。

from pathlib import PurePath

def looks_like_tar_gz(filename):
    parts = PurePath(filename).suffixes
    return parts[-2:] == [".tar", ".gz"]

for value in ["backup.tar.gz", "report.final.csv", "backup.gz"]:
    print(value, looks_like_tar_gz(value))

期待される真偽は順に True、False、False です。この関数はファイル名が期待する形かどうかを返すだけです。大文字小文字の違いを許容する必要がある場合は、業務側で命名規則を決めてから小文字化するなどの扱いを検討してください。無条件で変換すると、大小文字を区別する環境や既存の命名ルールとのずれを見落とします。

parts[-2:] は末尾2要素を取り出すスライスです。要素が1つしかないときも例外ではなく短いリストになるため、backup.gz では一致しません。この挙動を理解しておけば、parts[-2] を直接参照して要素不足で失敗するコードを避けられます。簡潔な式でも、どの入力で何が返るかを説明できることが大切です。

失敗しやすい境界条件を整理する

最初の落とし穴は、ファイル名の先頭のドットです。.env のような名前は隠しファイルの慣習に使われることがあり、拡張子の意味で読むとは限りません。Pythonのバージョンによって末尾ドットの扱いに変更もあるため、細かな境界条件は利用環境の公式ドキュメントで確認してください。この記事の簡易例を、すべてのPythonバージョンの形式判定仕様と見なしてはいけません。

次の落とし穴は、フォルダ名に含まれるドットです。release.v2/backup.tar.gz というパスでも、確認したいのは末尾のファイル名部分です。拡張子だけで受信先を決める場合、ファイル名の取り出しと保存先の安全な決定は別の処理として設計します。受信者が指定した相対パスをそのまま結合して保存すると、意図しない場所へ書き込む危険があります。

三つ目は、文字列の偽装です。backup.tar.gz.exe なら末尾は .exe です。見た目の途中に .tar.gz があっても、単純な部分文字列検索で圧縮ファイルだと判定してはいけません。Windowsで拡張子を非表示にしている場合は見た目と実名の違いにも注意が必要です。名称の照合は必要条件の一つですが、信頼できる入力かどうかの判断とは独立しています。

四つ目は、名前と中身の不一致です。送信者が任意に名前を付けられるなら、実体が別形式でも .tar.gz と名付けられます。運用では受信元の信頼性、サイズ上限、形式の検証、保存先、展開前の安全確認を組み合わせます。機密データを未知のオンライン判定サービスへアップロードして調べる方法は避け、組織で許可された検査経路を使ってください。

業務で使うときの判断基準

社内のバックアップ受入では、ファイル名のルール違反を早く発見したい場合があります。その段階なら suffix や suffixes は便利です。処理が軽く、実ファイルを開かずに候補を分類できます。たとえば受付一覧の中から .tar.gz 形式らしい名前を抽出し、担当者へ確認を促す用途なら、名前だけの判定であることを明記したうえで使えます。

一方、自動展開や自動配布の可否を決めるには不足します。名前が合格しても中身が正しいとは限らないため、実ファイルを扱う工程で別途形式・容量・安全性を検証する必要があります。圧縮ファイルは展開後の総容量が極端に大きいこともあり、名前だけで処理を開始するとリソース枯渇につながりかねません。受入と展開を分離し、失敗時には対象を隔離して原因を記録できる流れが望まれます。

ファイル形式の判定が目的なのか、命名規則の監査が目的なのかを最初に決めてください。前者なら実データの検査が必要です。後者なら pathlib の属性を使った静的な分類が役立ちます。二つの目的を混ぜないことが、短いコードを安全な業務手順に育てる第一歩です。

まとめ

suffix は最後の拡張子部分、suffixes は拡張子部分の一覧を返します。backup.tar.gz では .gz と ['.tar', '.gz'] という違いが出ます。ただし、いずれも名前の解析結果であり、圧縮形式や安全性の実証ではありません。練習では架空の名前で返り値の形を確認し、本番では命名規則の検査とファイル実体の検査を分けましょう。

公式資料

文書情報

記事タイトル
Python pathlibで.tar.gzを判定する:suffixとsuffixesの違い
作成日
更新日
Source URL
https://papanda925.com/?p=18505

ライセンス: 本記事のうち、当サイトが権利を有する本文・自作図表は、特記なき限り CC BY 4.0 で利用できます。生成AIを活用して作成・編集した内容を含みます。コードについて、別途ライセンス表示またはリンク先GitHubリポジトリのライセンスがある場合は、その条件を優先します。引用・第三者資料・画像・商標等は本ライセンスの対象外です。 利用ポリシー

タイトルとURLをコピーしました