[解決!Python]splitext関数やPath.stem/Path.suffix属性を使ってパスを拡張子とそれ以外の部分に分割するには:解決!Python
パスを、そこに含まれる拡張子とそれ以外の部分に分割したいことはよくある。これを行うにはsplitext関数やPath.stem/Path.suffix/Path.parent/Path.suffixes属性が使える。
# パスを拡張子とそれ以外の部分に分割する
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.