views:

255

answers:

4

How to get upper paths from a single path?

So say you have a path like:

'C:\a\b\c\d\'

How do I get to 'C:\a\b' or 'C:\a\b\c'

Is there a pythonic way to do this?

+10  A: 

See os.path

from os import path
path.dirname("C:\\a\\b\\c\\d\\")
Brian Campbell
No, you would refer to it as path.dirname if you did 'from os import path'.
sysrqb
+1: link to the documentation.
S.Lott
+4  A: 

Theres basic stuff like os.path methods.

If you want a list of the full path names of each successive parent in the directory tree, heres a one liner:

from os.path import dirname

def f1(n): return [n] if n == dirname(n) else [n] + f1(dirname(n))

print f1("/a/b/c/d/e/f/g")
John Ellinwood
+2  A: 

os.path.split("C:\\a\\b\\c") will return a tuple:

('C:\a\b', 'c')

You can continue to call split on the first element of the tuple.

Sam C
you are duplicating the functionality of a standard library, which id more robust (what if a path ends in '\' with your example?) and more portable (your example does not work under linux)
Paolo Tedesco
+2  A: 
>>> def go_up(path, n):
...     return os.path.abspath(os.path.join(*([path] + ['..']*n)))
>>> path = 'C:\\a\\b\\c\\d\\'
>>> go_up(path, 2)
'C:\\a\\b'
>>> go_up(path, 1)
'C:\\a\\b\\c'
>>> go_up(path, 0)
'C:\\a\\b\\c\\d'

Not being a regular user of os.path, I don't know if this is an appropriate/pythonic solution. I compared it to an alternate function, define as follows:

def go_up_2(path, n):
    for i in xrange(n):
        path = os.path.split(path)[0]
    return path

The first thing to note is that go_up_2('C:\\a\\b\\', 1) != go_up_2('c:\\a\\b', 1), where it does with the original go_up. However, performance is significantly better, if that is an issue (probably not, but I was looking for some definitive way to say my own algorithm was better):

import timeit

g1 = """import os.path
import ntpath
os.path = ntpath
def go_up(path, n):
    return os.path.abspath(os.path.join(*([path] + ['..']*n)))"""

g2 = """import os.path
import ntpath
os.path = ntpath
def go_up(path, n):
    for i in xrange(n-1):
        path = os.path.split(path)[0]
    return path"""

t1 = timeit.Timer("go_up('C:\\a\\b\\c\\d', 3)", setup=g1).timeit()
t2 = timeit.Timer("go_up('C:\\a\\b\\c\\d', 3)", setup=g2).timeit()

print t1
print t2

This outputs (on my machine):

133.364659071
30.101334095

Not very useful information, but I was playing around, and figured it should be posted here anyway.

Devin Jeanpierre