[解決!Python]splitext関数やPath.stem/Path.suffix属性を使ってパスを拡張子とそれ以外の部分に分割するには解決!Python

パスを、そこに含まれる拡張子とそれ以外の部分に分割したいことはよくある。これを行うにはsplitext関数やPath.stem/Path.suffix/Path.parent/Path.suffixes属性が使える。

» 2022年11月15日 05時00分 公開
[かわさきしんじDeep Insider編集部]

この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。

「解決!Python」のインデックス

連載目次

# パスを拡張子とそれ以外の部分に分割する
from os.path import splitext

path = '/dir0/dir1/somefile.txt'

root, ext = splitext(path)
print(f'root: {root}, ext: {ext}'# root: /dir0/dir1/somefile, ext: .txt

# Pathオブジェクトではparent属性とstem属性を組み合わせる
from pathlib import Path

path = Path(path)
print(f'path.stem: {path.stem}'# path.stem: somefile
print(f'path.suffix: {path.suffix}'# path.suffix: .txt
print(f'path.parent: {path.parent}'# path.parent: /dir0/dir1

root = Path(f'{path.parent}/{path.stem}')
print(f'root: {root}, ext: {path.suffix}'# root: /dir0/dir1/somefile, ext: .txt

# 拡張子が連続している場合にそれらを拡張子として分割するには
path = '/dir0/dir1/somefile.tar.gz'
root, ext = splitext(path)
print(f'root: {root}, ext: {ext}'# root: /dir0/dir1/somefile.tar, ext: .gz

def mysplitext(path):
    root, ext = splitext(path)
    exts = ext
    while ext != '':
        root, ext = splitext(root)
        exts = ext + exts
    return root, exts

root, ext = mysplitext(path)
print(f'root: {root}, ext: {ext}'# root: /dir0/dir1/somefile, ext: .tar.gz

path = Path(path)  # root: /dir0/dir1/somefile, ext: .tar.gz
root = Path(f'{path.parent}/{path.stem}')
ext = path.suffix
print(f'root: {root}, ext: {ext}'# root: /dir0/dir1/somefile.tar, ext: .gz

print(path.suffixes)  # ['.tar', '.gz']

def mysplitext(path):
    parent = str(path.parent)
    parent = '' if parent == '.' else parent
    tmp = path.stem
    while True:
        stem = Path(tmp).stem
        if stem == tmp:
            break
        tmp = stem
    suffixes = ''.join(path.suffixes)
    root = f'{parent}/{stem}' if parent else stem
    return root, suffixes

root, ext = mysplitext(path)
print(f'root: {root}, ext: {ext}'# root: /dir0/dir1/somefile, ext: .tar.gz


os.pathモジュールのsplitext関数

 os.pathモジュールには渡されたパスを、拡張子とそれ以外の部分に分割するsplitext関数がある(引数には文字列、Pathオブジェクトなどを指定できる)。splitext関数はパスを与えるとそれを「(拡張子以外, 拡張子)」というタプルに含めて返送する。

 以下に例を示す。

from os.path import splitext

path = '/dir0/dir1/somefile.txt'

root, ext = splitext(path)
print(f'root: {root}, ext: {ext}'# root: /dir0/dir1/somefile, ext: .txt


 この例ではパスとして「'/dir0/dir1/somefile.txt'」をsplitext関数に渡している。そのため、拡張子とそれ以外に分割された「('/dir0/dir1/somefile', '.txt')」というタプルが返送されていることが分かる。

pathlibモジュールのPath.stem/Path.suffix属性

 一方、pathlibモジュールのPathクラスにはstem属性とsuffix属性がある。stem属性はパスを構成する最終要素の拡張子よりも前の部分を表し、suffix属性は拡張子を表す。そのため、単にこれら2つを結合するだけではsplitext関数とは異なる結果になることがある。

 以下に例を示す。

from pathlib import Path

path = Path(path)  # '/dir0/dir1/somefile.txt'
print(f'path.stem: {path.stem}'# path.stem: somefile
print(f'path.suffix: {path.suffix}'# path.suffix: .txt


 変数pathには先ほどの内容('/dir0/dir1/somefile.txt')をPathクラスのオブジェクトにしたものが代入されている。そして、そのstem属性はパスを構成する最終要素(somefile.txt)から拡張子を取り除いたものになっている。これに対して、suffix属性は拡張子になっている。

 splitext関数では「パスの構成要素全てから拡張子を除いたもの」と「拡張子」が得られていたので、Path.stem/Path.suffix属性とsplitext関数の戻り値が完全に対応しているわけではないことには注意しよう。同様な結果を得るには、パスを構成する要素のうち、最終要素よりも前の部分を表すPath.parent属性を使える。

print(f'path.parent: {path.parent}'# path.parent: /dir0/dir1


 よって、splitext関数と同様な結果を得るには以下のようにすればよい。

root = Path(f'{path.parent}/{path.stem}')
print(f'root: {root}, ext: {path.suffix}'# root: /dir0/dir1/somefile, ext: .txt


拡張子が複数ある場合

Copyright© Digital Advantage Corp. All Rights Reserved.

スポンサーからのお知らせPR

注目のテーマ

AI for エンジニアリング
「サプライチェーン攻撃」対策
1P情シスのための脆弱性管理/対策の現実解
OSSのサプライチェーン管理、取るべきアクションとは
Microsoft & Windows最前線2024
システム開発ノウハウ 【発注ナビ】PR
あなたにおすすめの記事PR

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。