[解決!Python]splitext関数でファイルパスから拡張子を取得するには:解決!Python
os.path.splitext関数は渡されたパスを拡張子とそれ以外の部分に分割する。その基本的な使い方と注意点、拡張子ごとに処理を切り分けるサンプルコードを紹介する。
from os.path import splitext
# os.path.splitext関数はパスを拡張子とそれ以外に分割する
w_file = 'C:\\tmp\\pytips\\foo.txt'
u_file = '/tmp/pytips/foo.txt'
result = splitext(w_file)
print(result) # ('C:\\tmp\\pytips\\foo', '.txt')
result = splitext(u_file)
print(result) # ('/tmp/pytips/foo', '.txt')
w_dir = 'C:\\tmp\\pytips\\'
u_dir = '/tmp/pytips/'
result = splitext(w_dir)
print(result) # ('C:\\tmp\\pytips\\', '')
result = splitext(u_dir)
print(result) # ('/tmp/pytips/', '')
# PathクラスのインスタンスでもOK
from pathlib import Path
u_file = Path(u_file)
print(u_file) # /tmp/pytips/foo.txt
result = splitext(u_file)
print(result) # ('/tmp/pytips/foo', '.txt')
# os.path.splitext関数は最後の拡張子以降を拡張子として扱う
f = '/tmp/foo/bar.tar.gz'
result = splitext(f)
print(result) # ('/tmp/foo/bar.tar', '.gz')
f = '/tmp/foo/readme'
result = splitext(f) # 拡張子がなければタプルの拡張子部分は空文字列
print(result) # ('/tmp/foo/readme', '')
# 拡張子に応じて何らかの処理を行う
# 準備
from pathlib import Path
d = Path('pytips/test')
d.mkdir(parents=True, exist_ok=True)
f0 = Path(d, 'foo.txt') # 'pytips/test/foo.txt'
f1 = d / Path('bar.csv') # 'pytips/test/bar.csv'
f2 = d / 'baz.tsv' # pytips/test/baz.tsv'
print(d) # pytips/test
print(f0) # pytips/test/foo.txt
print(f1) # pytips/test/bar.csv
print(f2) # pytips/test/baz.tsv
f0.touch()
f1.touch()
f2.touch()
# Path.iterdirメソッドでディレクトリを走査する
for item in d.iterdir():
root, ext = splitext(item)
match(ext):
case '.txt':
print('processing a text file:', item)
case '.csv' | '.tsv':
print('processing a csv/tsv file:', item)
case _:
print('do nothing:', item)
# os.scandir関数でディレクトリを走査する
import os
for item in os.scandir(d):
root, ext = splitext(item) # DirEntryクラスのインスタンスでもOK
if ext == '.txt':
print('processing a text file:', item.name)
elif ext == '.csv' or ext == '.tsv':
print('processing a csv/tsv file:', item.name)
else:
print('do nothing:', item.name)
os.path.splitext関数
os.pathモジュールにはパスを特定の条件で分割する関数が幾つかある。
- os.path.split関数:パスを「(パスの末尾より前, パスの末尾)」という2要素のタプルに分割する
- os.path.splitdrive関数:パスを「(ドライブ, それ以外)」という2要素のタプルに分割する
- os.path.splitext関数:パスを「(拡張子以外の部分, 拡張子)」という2要素のタプルに分割する
- os.path.splitroot関数:パスを「(ドライブ, パスの末尾より前, パスの末尾)」という3要素のタプルに分割する(Python 3.12以降)
このうち、以下ではos.path.splitext関数を使って、パスを拡張子とそれ以外の部分に分割する方法を紹介する。
以下にos.path.splitext関数の構文を示す。
os.path.splitext(path)
os.path.splitext関数はパラメーターを1つ持ち、これにパスを渡すと「(拡張子以外の部分, 拡張子)」という2つの要素からなるタプルが返される。
基本的な例を以下に示す。
from os.path import splitext
# os.path.splitext関数はパスを拡張子とそれ以外に分割する
w_file = 'C:\\tmp\\pytips\\foo.txt'
u_file = '/tmp/pytips/foo.txt'
result = splitext(w_file)
print(result) # ('C:\\tmp\\pytips\\foo', '.txt')
result = splitext(u_file)
print(result) # ('/tmp/pytips/foo', '.txt')
変数w_fileにはWindows形式のパス(テキストファイルを表している)が、変数u_fileにはUnix形式のパス(こちらもテキストファイルを表している)が代入されている。これらをos.path.splitext関数に渡すと結果は「('C:\\tmp\\pytips\\foo', '.txt')」「('/tmp/pytips/foo', '.txt')」と拡張子以外の部分と拡張子を含んだタプルが得られる。
注意したいのは、拡張子の部分がピリオドで始まっている点だ。
次のように拡張子を含まないパス(多くの場合はディレクトリやフォルダーを意味しているだろう)を渡すと、タプルの拡張子部分は空文字列となる。
w_dir = 'C:\\tmp\\pytips\\'
u_dir = '/tmp/pytips/'
result = splitext(w_dir)
print(result) # ('C:\\tmp\\pytips\\', '')
result = splitext(u_dir)
print(result) # ('/tmp/pytips/', '')
ここまでパスとして文字列を渡していたが、os.path.splitext関数にはいわゆる「path-likeオブジェクト」を渡してもよい。そうしたオブジェクトとして典型的なのがpathlibモジュールのPathクラスのインスタンスだ。
from pathlib import Path
u_file = Path(u_file)
print(u_file) # /tmp/pytips/foo.txt
result = splitext(u_file)
print(result) # ('/tmp/pytips/foo', '.txt')
この例では、文字列として表現されていたパスをPathクラスのインスタンスに変換子、それをos.path.splitext関数に渡している。
パスの最後の構成要素が複数のピリオドを含んでいる場合、os.path.splitext関数は最後のピリオド以降を拡張子として扱う。以下に例を示す。
f = '/tmp/foo/bar.tar.gz'
result = splitext(f)
print(result) # ('/tmp/foo/bar.tar', '.gz')
ここではパスは/tmp/fooディレクトリにあるbar.tar.gzファイルを指しているが、これをos.path.splitext関数に渡すと最後のピリオド以降の「.gz」が拡張子として扱われる。
逆に拡張子がない場合は(先ほども見たが)、戻り値となるタプルの拡張子部分は空文字列になる。以下の例ではreadmeファイルを指しているパスをos.path.splitext関数に渡しているが、戻り値であるタプルの拡張子部分は空文字列になっている。
f = '/tmp/foo/readme'
result = splitext(f) # 拡張子がなければタプルの拡張子部分は空文字列
print(result) # ('/tmp/foo/readme', '')
拡張子に応じて何らかの処理を行う
最後に、os.path.splitext関数で拡張子を取り出して、その種類に応じた処理を行う例を示す。その準備として、ここではカレントディレクトリにpytipsディレクトリを作成し、その下にさらにtestディレクトリを作成して、そこに3つのファイルを配置している。
from pathlib import Path
d = Path('pytips/test')
d.mkdir(parents=True, exist_ok=True)
f0 = Path(d, 'foo.txt') # 'pytips/test/foo.txt'
f1 = d / Path('bar.csv') # 'pytips/test/bar.csv'
f2 = d / 'baz.tsv' # pytips/test/baz.tsv'
print(d) # pytips/test
print(f0) # pytips/test/foo.txt
print(f1) # pytips/test/bar.csv
print(f2) # pytips/test/baz.tsv
f0.touch()
f1.touch()
f2.touch()
最初にPath.iterdirメソッドでpytips/testディレクトリを走査して、そこにある3つのファイルの拡張子を得て、match文で処理を分岐させる例だ。
for item in d.iterdir():
root, ext = splitext(item)
match(ext):
case '.txt':
print('processing a text file:', item)
case '.csv' | '.tsv':
print('processing a csv/tsv file:', item)
case _:
print('do nothing:', item)
2つ目のcaseブロックでは「case '.csv' | '.tsv':」として拡張子が'.csv'と'.tsv'の場合の処理をまとめている(実際には区切り文字が異なるため、このように処理をまとめるのは難しいかもしれない)。
同じことをos.scandir関数とif文の組み合わせで行う例は以下の通りだ。
import os
for item in os.scandir(d):
root, ext = splitext(item) # DirEntryクラスのインスタンスでもOK
if ext == '.txt':
print('processing a text file:', item.name)
elif ext == '.csv' or ext == '.tsv':
print('processing a csv/tsv file:', item.name)
else:
print('do nothing:', item.name)
os.scandir関数で列挙されるのはDirEntryクラスのインスタンスだが、これもpath-likeオブジェクトなので、os.path.splitext関数には問題なく渡せる点にも注意しよう。
Copyright© Digital Advantage Corp. All Rights Reserved.