os.path – Platform-independent manipulation of file names.

Purpose:Parse, build, test, and otherwise work on file names and paths.
Available In:1.4 and later

Writing code to work with files on multiple platforms is easy using the functions included in the os.path module. Even programs not intended to be ported between platforms should use os.path for reliable filename parsing.

Parsing Paths

The first set of functions in os.path can be used to parse strings representing filenames into their component parts. It is important to realize that these functions do not depend on the paths actually existing; they operate solely on the strings.

Path parsing depends on a few variable defined in os:

  • os.sep - The separator between portions of the path (e.g., “/” or “\”).
  • os.extsep - The separator between a filename and the file “extension” (e.g., “.”).
  • os.pardir - The path component that means traverse the directory tree up one level (e.g., “..”).
  • os.curdir - The path component that refers to the current directory (e.g., “.”).

split() breaks the path into 2 separate parts and returns the tuple. The second element is the last component of the path, and the first element is everything that comes before it.

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() returns a value equivalent to the second part of the split() value.

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() returns the first part of the split path:

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() works like split() but divides the path on the extension separator, rather than the directory separator.

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() takes a list of paths as an argument and returns a single string that represents a common prefix present in all of the paths. The value may represent a path that does not actually exist, and the path separator is not included in the consideration, so the prefix might not stop on a separator boundary.

import os.path

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

In this example the common prefix string is /one/two/three, even though one path does not include a directory named three.

$ python ospath_commonprefix.py

['/one/two/three/four', '/one/two/threefold', '/one/two/three/']
/one/two/three

Building Paths

Besides taking existing paths apart, you will frequently need to build paths from other strings.

To combine several path components into a single value, use 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

It’s also easy to work with paths that include “variable” components that can be expanded automatically. For example, expanduser() converts the tilde (~) character to a user’s home directory.

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() is more general, and expands any shell environment variables present in the path.

import os.path
import os

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

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

/path/to/VALUE

Normalizing Paths

Paths assembled from separate strings using join() or with embedded variables might end up with extra separators or relative path components. Use normpath() to clean them up:

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

To convert a relative path to a complete absolute filename, use 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/Documents/PyMOTW/src/PyMOTW/ospath"
".." : "/Users/dhellmann/Documents/PyMOTW/src/PyMOTW"
"./one/two/three" : "/Users/dhellmann/Documents/PyMOTW/src/PyMOTW/ospath/one/two/three"
"../one/two/three" : "/Users/dhellmann/Documents/PyMOTW/src/PyMOTW/one/two/three"

File Times

Besides working with paths, os.path also includes some functions for retrieving file properties, which can be more convenient than calling 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  : Thu Feb 21 06:36:29 2013
Modified time: Sat Feb 19 19:18:23 2011
Change time  : Sat Jul 16 12:28:42 2011
Size         : 495

Testing Files

When your program encounters a path name, it often needs to know whether the path refers to a file or directory. If you are working on a platform that supports it, you may need to know if the path refers to a symbolic link or mount point. You will also want to test whether the path exists or not. os.path provides functions to test all of these conditions.

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

Traversing a Directory Tree

os.path.walk() traverses all of the directories in a tree and calls a function you provide passing the directory name and the names of the contents of that directory. This example produces a recursive directory listing, ignoring .svn directories.

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
Standard library documentation for this module.
os
The os module is a parent of os.path.
File Access
Other tools for working with files.
Bookmark and Share