[解決!Python]splitdrive関数でファイルパスをドライブ文字とその他の部分に分割するには:解決!Python
Windowsではファイルパスにドライブ文字が含まれる場合がある。os.pathモジュールのsplitdrive関数を使って、ドライブ文字とその他に分割する方法や、UNIXでこれと同様な処理を行う方法などを紹介する。
from os.path import splitdrive
wp = 'C:\\tmp\\foo\\bar\\baz.txt'
result = splitdrive(wp)
print(result)
# 出力結果:
# macOS:('', 'C:\\tmp\\foo\\bar\\baz.txt')
# Windows:('C:', '\\tmp\\foo\\bar\\baz.txt')
# UNIX形式のパスを渡すとドライブ要素は常に空文字列
up = '/tmp/foo/bar/baz.txt'
result = splitdrive(up)
print(result) # ('', '/tmp/foo/bar/baz.txt')
# Windows上で動作するPythonと同様にパスを分割する
import ntpath
result = ntpath.splitdrive(wp)
print(result) # ('C:', '\\tmp\\foo\\bar\\baz.txt')
uncp = '\\\\server\\SharedFolders\\pytips'
result = splitdrive(uncp)
print(result)
# macOS:('', '\\\\server\\SharedFolders\\pytips')
# Windows:('\\\\server\\SharedFolders', '\\pytips')
uncp = '\\\\.\\z:\\pytips'
result = splitdrive(uncp)
print(result)
# 出力結果:
# macOS:('', '\\\\.\\z:\\pytips')
# Windows:('\\\\.\\z:', '\\pytips')
# 相対パス
up = 'foo/bar/baz.txt'
result = splitdrive(up)
print(result) # ('', 'foo/bar/baz.txt')
wp = 'd:foo\\bar\\baz.txt' # fooはDドライブのカレントディレクトリにある
result = splitdrive(wp)
print(result)
# 出力結果:
# macOS:('', 'd:foo\\bar\\baz.txt')
# Windows:('d:', 'foo\\bar\\baz.txt')
# path-like object
from pathlib import Path
wp = Path('C:\\tmp\\foo\\bar\\baz.txt')
result = splitdrive(wp)
print(result)
# 出力結果:
# macOS:('', 'C:\\tmp\\foo\\bar\\baz.txt')
# Windows:('C:', '\\tmp\\foo\\bar\\baz.txt')
result = ntpath.splitdrive(wp)
print(result) # ('C:', '\\tmp\\foo\\bar\\baz.txt')
os.path.splitdrive関数
os.pathモジュールにはパスを特定の条件で分割する関数が幾つかある。
- os.path.split関数:パスを「(パスの末尾より前, パスの末尾)」という2要素のタプルに分割する
- os.path.splitdrive関数:パスを「(ドライブ, それ以外)」という2要素のタプルに分割する
- os.path.splitext関数:パスを「(拡張子以外の部分, 拡張子)」という2要素のタプルに分割する
- os.path.splitroot関数:パスを「(ドライブ, パスの末尾より前, パスの末尾)」という3要素のタプルに分割する(Python 3.12以降)
このうち、以下ではos.path.splitdrive関数を使って、パスをドライブ(ドライブ文字)とそれ以外の部分に分割する方法を紹介する。
以下にos.path.splitdrive関数の構文を示す。
os.path.splitextdrive(path)
os.path.split関数はパラメーターを1つ持ち、これにパスを渡すと「(パスのドライブ文字, その他の要素)」という2つの要素からなるタプルが返される。パスにドライブ文字が含まれるのはWindowsなので、UNIX(POSIX)環境では戻り値の第0要素は常に空文字列となる。
基本的な例を以下に示す。
from os.path import splitdrive
wp = 'C:\\tmp\\foo\\bar\\baz.txt'
result = splitdrive(wp)
print(result)
# 出力結果:
# macOS:('', 'C:\\tmp\\foo\\bar\\baz.txt')
# Windows:('C:', '\\tmp\\foo\\bar\\baz.txt')
この例では、変数wpにはWindows形式の絶対パスを代入している。これをos.path.splitdrive関数に渡すと、戻り値はUNIXならドライブ部分は空文字列になり、残りの部分に関数へ渡したパスがそのまま含まれる。一方、Windowsではドライブ文字とその他の部分が分割される。
UNIX形式のパスではUNIXでも、Windowsでも戻り値のドライブ要素は空文字列となる。
up = '/tmp/foo/bar/baz.txt'
result = splitdrive(up)
print(result) # ('', '/tmp/foo/bar/baz.txt')
UNIX環境でWindows形式のパスを操作する場合に、Windows環境と同様なパス分割をしたければntpathモジュールをインポートして、そのsplitdrive関数を使用する。
import ntpath
result = ntpath.splitdrive(wp)
print(result) # ('C:', '\\tmp\\foo\\bar\\baz.txt')
Windowsのファイル共有パス(UNCパス)を与えた場合、UNIX環境ではドライブ文字要素は空文字列に、Windows環境ではドライブ文字要素にはサーバ名と共有名がドライブ文字要素になり、その他の部分と分割される。以下に例を示す。
uncp = '\\\\server\\SharedFolders\\pytips'
result = splitdrive(uncp)
print(result)
# 出力結果:
# macOS:('', '\\\\server\\SharedFolders\\pytips')
# Windows:('\\\\server\\SharedFolders', '\\pytips')
uncp = '\\\\.\\z:\\pytips'
result = splitdrive(uncp)
print(result)
# 出力結果:
# macOS:('', '\\\\.\\z:\\pytips')
# Windows:('\\\\.\\z:', '\\pytips')
相対パスを指定した場合も、ドライブ文字が含まれていれば、分割される。
# 相対パス
up = 'foo/bar/baz.txt'
result = splitdrive(up)
print(result) # ('', 'foo/bar/baz.txt')
wp = 'd:foo\\bar\\baz.txt' # fooはDドライブのカレントディレクトリにある
result = splitdrive(wp)
print(result)
# 出力結果:
# macOS:('', 'd:foo\\bar\\baz.txt')
# Windows:('d:', 'foo\\bar\\baz.txt')
最初の例はUNIX形式の相対パスなので、ドライブ文字要素は空文字列になる。次の例はWindows形式の相対パスだが、パスの先頭に「d:」とドライブ文字がある点に注意。fooディレクトリはD:ドライブのカレントディレクトリにあるということだ。これをos.path.splitdrive関数に渡すと、UNIXではドライブ文字要素は空文字列に、Windowsではドライブ文字と他の部分が分割される。
path-like objectを渡すこともできる。簡単な例を以下に示す。
from pathlib import Path
wp = Path('C:\\tmp\\foo\\bar\\baz.txt')
result = splitdrive(wp)
print(result)
# 出力結果:
# macOS:('', 'C:\\tmp\\foo\\bar\\baz.txt')
# Windows:('C:', '\\tmp\\foo\\bar\\baz.txt')
result = ntpath.splitdrive(wp)
print(result) # ('C:', '\\tmp\\foo\\bar\\baz.txt')
なお、本稿冒頭ではUNIX(POSIX)環境ではドライブ文字要素は常に空文字列になると書いたが、これはposixlib.splitdrive関数の実装が次のようになっているからだ。
def splitdrive(p):
"""Split a pathname into drive and path. On Posix, drive is always
empty."""
p = os.fspath(p)
return p[:0], p
os.fspath関数はパスのファイルシステム表現となる文字列またはバイト列を返す。そして、その先頭から0番目の要素の手前まで(つまり、空文字列か空のバイト列)と、パスのファイルシステム表現をタプルにまとめたものを戻り値とするようになっている。また、コメントにも「POSIXでは、drive要素は常に空」とある。そのため、本稿でもそのように表現している。
Copyright© Digital Advantage Corp. All Rights Reserved.