Pythonでパスからファイル名を取得する【os.path.basename】

245, 2021-05-08

目次

Pythonでパスからファイル名を取得する

Pythonでは文字列のパスに書かれているファイル名を関数1つで取得することができます。
Pythonではそういった用途にはos.path.basename()を使います。

ファイル名を取得したいケースは意外と多いものです。
例えばファイルをコピーしたい時にコピー元のファイル名を維持してコピー先に同じファイル名で保存したい時です。
コピー先で同じファイル名を使いたい場合はコピー元のパスからファイル名を取得する必要があります。
そういったときにos.path.basename()を使うとパスからファイル名を取得できます。

結論から言うとos.path.basename()は↓のように使います。

import os

path = '/path/to/my/file.txt'
base = os.path.basename(path)
print(base)
# file.txt

この記事ではos.path.basename()を使ったファイル名の取得方法の他、以下の方法についても見ていきます。

  • os.path.basename()でファイル名を取得

  • 拡張子なしのファイル名を取得

  • os.path.dirname()でフォルダ名を取得

  • 同名のファイルにコピーする

os.path.basename()でファイル名を取得

os.path.basename()はパスからベース名、つまりファイル名を取得する関数です。

この関数は↓のような構造になっています。

os.path.basename(path)

第1引数のpathにはパスを渡します。
os.path.basenameはこのpathを解析し、そこからファイル名を取り出して返します。

import os

path = '/path/to/my/file.txt'
base = os.path.basename(path)
print(base)
# file.txt

os.path.basename()が受け入れるpathのタイプは文字列かバイト列、またはos.PathLikeなオブジェクトに限られます。
たとえばos.path.basename()Noneを渡すと例外TypeErrorが送出されます。

try:
    os.path.basename(None)
except TypeError as e:
    print(e)
    # expected str, bytes or os.PathLike object, not NoneType

バイト列はクオートの頭にbを付けると作成できます。

path = b'/path/to/my/file.txt'
base = os.path.basename(path)
print(base)
# b'file.txt'

os.path.basename()にバイト列を渡した場合はその返り値もバイト列になっていることに注意してください。

os.PathLikeオブジェクトと言うのはpathlibで扱われるオブジェクトのベースクラスです。
つまりpathlibPathオブジェクトをos.path.basename()に渡すことができます。

from pathlib import Path

path = Path('/path/to/my/file.txt')
base = os.path.basename(path)
print(base)
# file.txt

拡張子なしのファイル名を取得

os.path.basename()は拡張子がくっついてきます。
拡張子なんていらないよ! という場合は↓のようにします。

  1. os.path.basename()でファイル名を取る

  2. os.path.splitext()でファイル名を分割する

  3. その結果の0番目の要素を取る

つまり↓のようにします。

path = '/path/to/my/file.txt'
base = os.path.basename(path)
fname = os.path.splitext(base)[0]
print(fname)
# file

os.path.splitext()はファイル名からファイル名部分と拡張子部分を分割します。

その結果はタプルで返ってきます。

path = 'file.txt'
result = os.path.splitext(path)
print(result)
# ('file', '.txt')

分割されたファイル名部分はタプルの0番目に入っているので、これを添え字で取り出します。

abc.def.ghiのようなファイル名の場合

abc.def.ghifile.tar.gzのようなファイル名の場合は先ほどの方法ではうまく行きません。
そうした場合はos.path.splitext()を連続して使います。

path = '/path/to/my/abc.def.ghi'
base = os.path.basename(path)
fname = os.path.splitext(base)[0]
fname = os.path.splitext(fname)[0]
print(fname)
# abc

あるいはos.path.basename()でファイル名を取得してからそのファイル名を.で分割し、その先頭の要素を取得します。

path = '/path/to/my/abc.def.ghi'
base = os.path.basename(path)
fname = base.split('.')[0]
print(fname)
# abc

↑の方法であれば、ドットの数が多くなっても対応できそうです。

os.path.dirname()でフォルダ名を取得

ファイル名の類似としてフォルダ名(ディレクトリ名)を取得したい場合もあります。
その場合はos.path.dirname()を使います。

path = '/path/to/my/file.txt'
dirname = os.path.dirname(path)
print(dirname)
# /path/to/my

上の方法だとパスで区切られたディレクトリがすべて取得されます。
最後のディレクトリ名だけを取得したい場合は↓のようにします。

path = '/path/to/my/file.txt'
dirname = os.path.dirname(path)
dirname = os.path.split(dirname)[-1]
print(dirname)
# my

os.path.split()はパスをセパレーターで分割します。

同名のファイルにコピーする

コピー元のファイル名と同名のファイルを作り、そこに内容をコピーするサンプルです。

import os

srcpath = './src/file.txt'  # ソースとなるファイルのパス
with open(srcpath, 'r', encoding='utf-8') as fin:
    content = fin.read()  # 中身を読み込む

dstdir = './dst'  # 保存先のディレクトリ
fname = os.path.basename(srcpath)  # ファイル名を取得
dstpath = os.path.join(dstdir, fname)  # ディレクトリ名とファイル名を合成

with open(dstpath, 'w', encoding='utf-8') as fout:
    fout.write(content)  # 書き込む

↑で使っているos.path.join()は複数の要素をパスとして合成します。

↑の例だと./dstfile.txtをパスとして合成してます。

おわりに

今回はPythonでファイル名を取得する方法を見てみました。
ファイル名の取得と言うのはけっこうあるあるなケースなので、この記事を皆さんのブックマークに登録していただけたらいざという時に役に立つかもしれません。

ファイル名、それはパスの深淵

ファイル名を覗くとき、覗かれている