[解決!Python]splitroot関数でファイルパスをドライブ、ルート、それ以外に分割するには解決!Python

ファイルパスをドライブ、ルート、それ以降に分割するにはos.pathモジュールのsplitroot関数を使える。その使い方、WindowsとUNIXでの動作の違い、Windowsと同様な分割結果を得るための方法などを紹介する。

» 2024年04月02日 05時00分 公開
[かわさきしんじDeep Insider編集部]
「解決!Python」のインデックス

連載目次

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')


「解決!Python」のインデックス

解決!Python

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。