Dominik
Dominik

Reputation: 377

Working with relative paths

When I run the following script:

c:\Program Files\foo\bar\scripy.py

How can I refer to directory 'foo'?

Is there a convenient way of using relative paths?

I've done it before with the string module, but there must be a better way (I couldn't find it in os.path).

Upvotes: 1

Views: 4171

Answers (4)

Edgar Velasquez Lim
Edgar Velasquez Lim

Reputation: 2446

os.path.dirname(path)

Will return the second half of a SPLIT that is performed on the path parameter. (head - the directory and tail, the file) Put simply it returns the directory the path is in. You'll need to do it twice but this is probably the best way.

Python Docs on path functions:

http://docs.python.org/library/os.path#os.path.expanduser

Upvotes: 1

I have recently started using the unipath library instead of os.path. Its object-oriented representations of paths are much simpler:

from unipath import Path

original = Path(__file__) # .absolute() # r'c:\Program Files\foo\bar\scripy.py'
target = original.parent.parent

print target # Path(u'c:\\Program Files\\foo')

Path is a subclass of str so you can use it with standard filesystem functions, but it also provides alternatives for many of them:

print target.isdir() # True

numbers_dir = target.child('numbers')

print numbers_dir.exists() # False
numbers_dir.mkdir()
print numbers_dir.exists() # True

for n in range(10):
    file_path = numbers_dir.child('%s.txt' % (n,))
    file_path.write_file("Hello world %s!\n" % (n,), 'wt')

Upvotes: 1

Michael Dillon
Michael Dillon

Reputation: 32392

This is a bit tricky. For instance, the following code:

import sys
import os

z = sys.argv[0]
p = os.path.dirname(z)
f = os.path.abspath(p)

print "argv[0]={0} , dirname={1} , abspath={2}\n".format(z,p,f)

gives this output on Windows

argv[0]=../zzz.py , dirname=.. , abspath=C:\Users\michael\Downloads First of all, notice that argv has the slash which I typed in the command python ../zzz.py and the absolute path has the normal Windows backslashes. If you need to be cross platform you should probably refrain from putting regular slashes on Python command lines, and use os.sep to refer to the character that separated pathname components.

So far I have only partly answered your question. There are a couple of ways to use the value of f to get what you want. Brute force is to use something like:

targetpath = f + os.sep + ".." + os.sep + ".."

which would result in something like C:\Users\michael\Downloads\..\.. on Windows and /home/michael/../.. on Unix. Each .. goes back one step and is the equivalent of removing the pathname component.

But you could do better by breaking up the path:

target = f.split(os.sep)
targetpath = os.sep.join(target[:-2]

and rejoining all but the last two bits to get C:\Users on Windows and / on Unix. If you do that it might be a good idea to check that there are enough pathname components to remove.

Note that I ran the program above by typing python ../xxx.py. In other words I was not in the same working directory as the script, therefore getcwd() would not be useful.

Upvotes: 0

The os.path module includes various functions for working with paths like this. The convention in most operating system is to use .. to go "up one level", so to get the outside directory you could do this:

import os
import os.path

current_dir = os.getcwd() # find the current directory
print current_dir # c:\Program Files\foo\bar\scripy.py

parent = os.path.join(current_dir, "..") # construct a path to its parent
print parent # c:\Program Files\foo\bar\..

normal_parent = os.path.normpath(parent) # "normalize" the path
print normal_parent # c:\Program Files\foo

# or on one line:
print os.path.normpath(os.path.join(os.getcwd(), ".."))

Upvotes: 4

Related Questions