os.path – プラットホーム独自のファイル名を操作する

目的:ファイル名やパスに関連する解析、構築、テスト、その他
利用できるバージョン:1.4 以上

複数プラットホーム上のファイルを操作するコードを書くには os.path モジュールに含まれる関数を使用すると簡単です。そのプログラムが他プラットホーム間の移植性を考慮していなくても信頼性の高いファイル名の解析のために os.path を使用すべきです。

パスを解析する

os.path の関数の第1セットはファイル名をその要素の部品を表す文字列へ解析することに使用されます。これらの関数群は対象のパスが実際に存在するかどうかに関係なく、ただ単に文字列操作であることを理解することが重要です。

解析するパスは os で定義されている少しの変数に依存します。

  • os.sep - パスの区切りを表すセパレータ (例, “/” 又は “\“)
  • os.extsep - ファイル名とその “拡張子” の間のセパレータ (例, “.“)
  • os.pardir - 1階層上のディレクトリへ移動するパス要素 (例, “..“)
  • os.curdir - カレントディレクトリを参照するパス要素 (例, “.“)

split() はパスを2つに分割してそのタプルを返します。2番目の要素はパスの最後の要素で、最初の要素はその前に来るパス全部です。

import os.path

for path in [ '/one/two/three', 
              '/one/two/three/',
              '/',
              '.',
              '']:
    print '"%s" : "%s"' % (path, os.path.split(path))
$ python ospath_split.py
"/one/two/three" : "('/one/two', 'three')"
"/one/two/three/" : "('/one/two/three', '')"
"/" : "('/', '')"
"." : "('', '.')"
"" : "('', '')"

basename()split() した値の2番目の要素と同じ値を返します。

import os.path

for path in [ '/one/two/three', 
              '/one/two/three/',
              '/',
              '.',
              '']:
    print '"%s" : "%s"' % (path, os.path.basename(path))
$ python ospath_basename.py
"/one/two/three" : "three"
"/one/two/three/" : ""
"/" : ""
"." : "."
"" : ""

dirname()split() したパスの最初の要素を返します。

import os.path

for path in [ '/one/two/three', 
              '/one/two/three/',
              '/',
              '.',
              '']:
    print '"%s" : "%s"' % (path, os.path.dirname(path))
$ python ospath_dirname.py
"/one/two/three" : "/one/two"
"/one/two/three/" : "/one/two/three"
"/" : "/"
"." : ""
"" : ""

splitext()split() のように動作しますが、ディレクトリではなく拡張子をセパレータとしてパスを分割します。

import os.path

for path in [ 'filename.txt', 'filename', '/path/to/filename.txt', '/', '' ]:
    print '"%s" :' % path, os.path.splitext(path)
$ python ospath_splitext.py
"filename.txt" : ('filename', '.txt')
"filename" : ('filename', '')
"/path/to/filename.txt" : ('/path/to/filename', '.txt')
"/" : ('/', '')
"" : ('', '')

commonprefix() は引数としてパスのリストを受け取り、その全てのパスに共通する接頭辞である1つの文字列を返します。その値は実際に存在しないパスを表したり、パスセパレータを考慮していなかったりするかもしれません。そのため、その接頭辞として使用する文字列はセパレータの境界で停止しない可能性があります。

import os.path

paths = ['/one/two/three/four',
         '/one/two/threefold',
         '/one/two/three/',
         ]
print paths
print os.path.commonprefix(paths)

このサンプルでは、あるパスは three という名前のディレクトリを含まないけれど、共通の接頭辞は /one/two/three です。

$ python ospath_commonprefix.py
['/one/two/three/four', '/one/two/threefold', '/one/two/three/']
/one/two/three

パスを構築する

既存パスを分解した上で他の文字列からパスを構築する機会がよくあります。

複数のパスの要素を1つの文字列に結合するために join() を使用してください。

import os.path

for parts in [ ('one', 'two', 'three'),
               ('/', 'one', 'two', 'three'),
               ('/one', '/two', '/three'),
               ]:
    print parts, ':', os.path.join(*parts)
$ python ospath_join.py
('one', 'two', 'three') : one/two/three
('/', 'one', 'two', 'three') : /one/two/three
('/one', '/two', '/three') : /three

さらに自動的に展開される “変数” 要素を含むパスを操作することも簡単です。例えば expanduser() はチルダ (~) 文字をユーザのホームディレクトリに変換します。

import os.path

for user in [ '', 'dhellmann', 'postgres' ]:
    lookup = '~' + user
    print lookup, ':', os.path.expanduser(lookup)
$ python ospath_expanduser.py
~ : /Users/dhellmann
~dhellmann : /Users/dhellmann
~postgres : /Library/PostgreSQL/9.0

expandvars() はもっと一般的に、パスに存在するシェルの環境変数を展開します。

import os.path
import os

os.environ['MYVAR'] = 'VALUE'

print os.path.expandvars('/path/to/$MYVAR')
$ python ospath_expandvars.py
/path/to/VALUE

パスを標準化する

分割された文字列から join() を使用する、又は組み込み変数と共に最後に余分なセパレータが付く、又は要素の相対パスからパスが構成されたとします。そういったパスをクリーンアップするには normpath() を使用してください。

import os.path

for path in [ 'one//two//three', 
              'one/./two/./three', 
              'one/../one/two/three',
              ]:
    print path, ':', os.path.normpath(path)
$ python ospath_normpath.py
one//two//three : one/two/three
one/./two/./three : one/two/three
one/../one/two/three : one/two/three

相対パスから絶対パスのファイル名に変換するには abspath() を使用してください。

import os.path

for path in [ '.', '..', './one/two/three', '../one/two/three']:
    print '"%s" : "%s"' % (path, os.path.abspath(path))
$ python ospath_abspath.py
"." : "/Users/dhellmann/Devel/pymotw-ja/t2y/PyMOTW/ospath"
".." : "/Users/dhellmann/Devel/pymotw-ja/t2y/PyMOTW"
"./one/two/three" : "/Users/dhellmann/Devel/pymotw-ja/t2y/PyMOTW/ospath/one/two/three"
"../one/two/three" : "/Users/dhellmann/Devel/pymotw-ja/t2y/PyMOTW/one/two/three"

ファイル日付

パスの操作に加えて os.path は os.stat() を呼び出すよりももっと便利なファイルプロパティを取り出す関数も含みます。

import os.path
import time

print 'File         :', __file__
print 'Access time  :', time.ctime(os.path.getatime(__file__))
print 'Modified time:', time.ctime(os.path.getmtime(__file__))
print 'Change time  :', time.ctime(os.path.getctime(__file__))
print 'Size         :', os.path.getsize(__file__)
$ python ospath_properties.py
File         : ospath_properties.py
Access time  : Sun Feb 17 11:33:08 2013
Modified time: Fri Feb 11 08:38:29 2011
Change time  : Sat Jul 16 12:19:07 2011
Size         : 495

ファイルをテストする

あなたのプログラムがパス名に遭遇したとき、そのパス名はファイルかディレクトリを参照しているか調べる必要があることがよくあります。あなたがファイルかディレクトリの調査をサポートするプラットホーム上で操作するなら、そのパスはシンボリックリンクを参照するかマウントポイントかを知る必要があるかもしれません。さらにパスが存在するかどうかをテストしたいときもあるでしょう。 os.path はこういった全ての条件をテストする関数を提供します。

import os.path

for file in [ __file__, os.path.dirname(__file__), '/', './broken_link']:
    print 'File        :', file
    print 'Absolute    :', os.path.isabs(file)
    print 'Is File?    :', os.path.isfile(file)
    print 'Is Dir?     :', os.path.isdir(file)
    print 'Is Link?    :', os.path.islink(file)
    print 'Mountpoint? :', os.path.ismount(file)
    print 'Exists?     :', os.path.exists(file)
    print 'Link Exists?:', os.path.lexists(file)
    print
$ ln -s /does/not/exist broken_link
$ python ospath_tests.py
File        : ospath_tests.py
Absolute    : False
Is File?    : True
Is Dir?     : False
Is Link?    : False
Mountpoint? : False
Exists?     : True
Link Exists?: True

File        :
Absolute    : False
Is File?    : False
Is Dir?     : False
Is Link?    : False
Mountpoint? : False
Exists?     : False
Link Exists?: False

File        : /
Absolute    : True
Is File?    : False
Is Dir?     : True
Is Link?    : False
Mountpoint? : True
Exists?     : True
Link Exists?: True

File        : ./broken_link
Absolute    : False
Is File?    : False
Is Dir?     : False
Is Link?    : True
Mountpoint? : False
Exists?     : False
Link Exists?: True

ディレクトリツリーを移動する

os.path.walk() はツリーの全ディレクトリを移動して、ディレクトリ名を渡してそのディレクトリのコンテンツの名前を提供する関数を呼び出します。このサンプルは .svn ディレクトリを無視して再起的にディレクトリを辿ってコンテンツを生成します。

import os
import os.path
import pprint

def visit(arg, dirname, names):
    print dirname, arg
    for name in names:
        subname = os.path.join(dirname, name)
        if os.path.isdir(subname):
            print '  %s/' % name
        else:
            print '  %s' % name
    print

os.mkdir('example')
os.mkdir('example/one')
f = open('example/one/file.txt', 'wt')
f.write('contents')
f.close()
f = open('example/two.txt', 'wt')
f.write('contents')
f.close()
os.path.walk('example', visit, '(User data)')
$ python ospath_walk.py
example (User data)
  one/
  two.txt

example/one (User data)
  file.txt

See also

os.path
本モジュールの標準ライブラリドキュメント
os
os.path の親にあたる os モジュール
ファイルアクセス
ファイルを操作する他のツール
Bookmark and Share