[解決!Python]splitroot関数でファイルパスをドライブ、ルート、それ以外に分割するには:解決!Python
ファイルパスをドライブ、ルート、それ以降に分割するにはos.pathモジュールのsplitroot関数を使える。その使い方、WindowsとUNIXでの動作の違い、Windowsと同様な分割結果を得るための方法などを紹介する。
from os.path import splitroot
up = '/tmp/foo/bar/baz.txt'
result = splitroot(up) # UNIX環境ではドライブ要素は常に空文字列
print(result) # ('', '/', 'tmp/foo/bar/baz.txt')
wp = 'C:\\tmp\\foo\\bar\\baz.txt'
result = splitroot(wp) # Windows形式のパスは環境で結果が異なる
print(result)
# 出力結果:
# macOS:('', '', 'C:\\tmp\\foo\\bar\\baz.txt')
# Windows:('C:', '\\', 'tmp\\foo\\bar\\baz.txt')
import ntpath # Windowsと同じ結果を得るにはntpathモジュールを使う
result = ntpath.splitroot(wp)
print(result) # ('C:', '\\', 'tmp\\foo\\bar\\baz.txt')
# 相対パス
up = 'tmp/foo/bar/baz.txt'
result = splitroot(up)
print(result) # ('', '', 'tmp/foo/bar/baz.txt')
wp = 'tmp\\foo\\bar\\baz.txt'
result = splitroot(wp)
print(result) # ('', '', 'tmp\\foo\\bar\\baz.txt')
# ドライブ文字付の相対パス
wp = 'D:tmp\\foo\\bar\\baz.txt'
result = splitroot(wp)
print(result)
# 出力結果:
# macOS:('', '', 'D:tmp\\foo\\bar\\baz.txt')
# Windows:('D:', '', 'tmp\\foo\\bar\\baz.txt')
result = ntpath.splitroot(wp)
print(result) # ('D:', '', 'tmp\\foo\\bar\\baz.txt')
# UNCパス
uncp = '\\\\server\\SharedFolders\\pytips'
result = splitroot(uncp)
print(result)
# 出力結果:
# macOS:('', '', '\\\\server\\SharedFolders\\pytips')
# Windows:('\\\\server\\SharedFolders', '\\', 'pytips')
result = ntpath.splitroot(uncp)
print(result) # ('\\\\server\\SharedFolders', '\\', 'pytips')
# path-like object
from pathlib import Path
up = Path('/tmp/foo/bar/baz.txt')
result = splitroot(up)
print(result)
# 出力結果:
# macOS:('', '/', 'tmp/foo/bar/baz.txt')
# Windows:('', '\\', 'tmp\\foo\\bar\\baz.txt')
wp = Path('C:\\tmp\\foo\\bar\\baz.txt')
result = splitroot(wp)
print(result)
# 出力結果:
# macOS:('', '', 'C:\\tmp\\foo\\bar\\baz.txt')
# Windows:('C:', '\\', 'tmp\\foo\\bar\\baz.txt')
result = ntpath.splitroot(wp)
print(result) # ('C:', '\\', 'tmp\\foo\\bar\\baz.txt')
os.path.splitroot関数
os.pathモジュールにはパスを特定の条件で分割する関数が幾つかある。
- os.path.split関数:パスを「(パスの末尾より前, パスの末尾)」という2要素のタプルに分割する
- os.path.splitdrive関数:パスを「(ドライブ, それ以外)」という2要素のタプルに分割する
- os.path.splitext関数:パスを「(拡張子以外の部分, 拡張子)」という2要素のタプルに分割する
- os.path.splitroot関数:パスを「(ドライブ, パスの末尾より前, パスの末尾)」という3要素のタプルに分割する(Python 3.12以降)
このうち、以下ではos.path.splitroot関数を使って、パスをドライブ(ドライブ文字)要素とルート要素、それ以外の部分に分割する方法を紹介する。
以下にos.path.splitroot関数の構文を示す。
os.path.splitroot(path)
os.path.split関数はパラメーターを1つ持ち、これにパスを渡すと「(ドライブ要素, ルート要素, その他の要素)」という3つの要素からなるタプルが返される。パスにドライブ文字が含まれるのはWindowsなので、UNIX(POSIX)環境では戻り値の第0要素は常に空文字列となる。
UNIX環境では、os.path.splitroot関数は次のように振る舞う。
- ドライブ要素は常に空文字列
- ルート要素はシングルスラッシュ「/」もしくはダブルスラッシュ「//」、もしくは空文字列(相対パスの場合)
- ルート要素以降が最後の要素に含まれる
Windows環境では次のように振る舞う。
- ドライブ要素はドライブ文字か、サーバ名と共有名(ファイル共有のUNCパスの場合)、もしくは空文字列(ドライブ指定がない場合)
- ルート要素はパスを区切るセパレーターか(絶対パスの場合)、空文字列(相対パスの場合)。セパレーターは多くの場合バックスラッシュ「\」が使われる
- ルート要素以降が最後の要素に含まれる
基本的な例を以下に示す。
from os.path import splitroot
up = '/tmp/foo/bar/baz.txt'
result = splitroot(up) # UNIX環境ではドライブ要素は常に空文字列
print(result) # ('', '/', 'tmp/foo/bar/baz.txt')
この例ではUNIX形式の絶対パス(/tmp/foo/bar/baz.txt)をsplitroot関数に渡している。既に述べたように、UNIXではドライブ要素は常に空となる。この分割結果はWindows環境でも同じだ。
Windows形式の絶対パスを分割する例を以下に示す。
wp = 'C:\\tmp\\foo\\bar\\baz.txt'
result = splitroot(wp) # Windows形式のパスは環境で結果が異なる
print(result)
# 出力結果:
# macOS:('', '', 'C:\\tmp\\foo\\bar\\baz.txt')
# Windows:('C:', '\\', 'tmp\\foo\\bar\\baz.txt')
こちらはコードを実行する環境によって結果が異なる。UNIX環境ではドライブ要素とルート要素が空文字列で、パス全体が残りの要素に含まれる。Windows環境ではドライブ文字、ルートとなるバックスラッシュ、それ以外の要素に分割される。UNIX環境でWindowsと同じ結果を得るには、ntpathモジュールのsplitroot関数を使用する。
import ntpath # Windowsと同じ結果を得るにはntpathモジュールを使う
result = ntpath.splitroot(wp)
print(result) # ('C:', '\\', 'tmp\\foo\\bar\\baz.txt')
相対パスを渡した場合は、ルート要素が空文字列になる。従って、UNIX環境ではこの場合、ドライブ要素とルート要素が空文字列になる。
up = 'tmp/foo/bar/baz.txt'
result = splitroot(up)
print(result) # ('', '', 'tmp/foo/bar/baz.txt')
このことはWindowsでも基本的には同じだ。
wp = 'tmp\\foo\\bar\\baz.txt'
result = splitroot(wp)
print(result) # ('', '', 'tmp\\foo\\bar\\baz.txt')
ただし、Windowsでは相対パスにドライブ指定が付加されることがある。その場合は、ドライブ要素は空文字列ではないが、ルート要素は空文字列になる。UNIX環境でそうした相対パスを処理すると、全てが残りの要素に含まれる(Windows形式のパスは全てそうなる)。既に見たように、ntpath.splitroot関数を使えば同じ結果が得られる。
wp = 'D:tmp\\foo\\bar\\baz.txt'
result = splitroot(wp)
print(result)
# 出力結果:
# macOS:('', '', 'D:tmp\\foo\\bar\\baz.txt')
# Windows:('D:', '', 'tmp\\foo\\bar\\baz.txt')
result = ntpath.splitroot(wp)
print(result) # ('D:', '', 'tmp\\foo\\bar\\baz.txt')
ファイル共有で使われるUNCパスをWindows環境でos.path.splitroot関数に渡すと、サーバ名と共有名(とディレクトリのセパレーター)がドライブ要素に含まれる。ルート要素はディレクトリのセパレーターとなり、それ以降が残りの要素に含まれる。以下に例を示す。
uncp = '\\\\server\\SharedFolders\\pytips'
result = splitroot(uncp)
print(result)
# 出力結果:
# macOS:('', '', '\\\\server\\SharedFolders\\pytips')
# Windows:('\\\\server\\SharedFolders', '\\', 'pytips')
result = ntpath.splitroot(uncp)
print(result) # ('\\\\server\\SharedFolders', '\\', 'pytips')
最後にos.path.splitroot関数にはpath-like objectも渡せる。以下に例を示す(説明は不要だろう)。
from pathlib import Path
up = Path('/tmp/foo/bar/baz.txt')
result = splitroot(up)
print(result)
# 出力結果:
# macOS:('', '/', 'tmp/foo/bar/baz.txt')
# Windows:('', '\\', 'tmp\\foo\\bar\\baz.txt')
wp = Path('C:\\tmp\\foo\\bar\\baz.txt')
result = splitroot(wp)
print(result)
# 出力結果:
# macOS:('', '', 'C:\\tmp\\foo\\bar\\baz.txt')
# Windows:('C:', '\\', 'tmp\\foo\\bar\\baz.txt')
result = ntpath.splitroot(wp)
print(result) # ('C:', '\\', 'tmp\\foo\\bar\\baz.txt')
Copyright© Digital Advantage Corp. All Rights Reserved.