marw
marw

Reputation: 3119

Joining: string and absolute path with os.path

Why is this not working, what am I doing wrong?

>>> p1 = r'\foo\bar.txt'
>>> os.path.join('foo1', 'foo2', os.path.normpath(p1))
'\\foo\\bar.txt'

I expected this:

'foo1\\foo2\\foo\\bar.txt'

Edit:

A Solution

>>> p1 = r'\foo\bar.txt'
>>> p1 = p1.strip('\\') # Strip '\\' so the path would not be absolute 
>>> os.path.join('foo1', 'foo2', os.path.normpath(p1))
'foo1\\foo2\\foo\\bar.txt'

Upvotes: 7

Views: 21983

Answers (3)

NuclearPeon
NuclearPeon

Reputation: 6039

If you want the target behaviour of os.path.join to join two absolute paths together, strip out the separator:

import os
p1 = os.path.join(os.sep, 'foo1', 'foo2')
p2 = os.path.join(os.sep, 'foo', 'bar.txt')

os.path.join(p1, p2.lstrip(os.sep))

If you want to modify the paths, you can also do cool things like this using list comprehensions:

# Make sure all folder names are lowercase:
os.path.join(p1, *[x.lower() for x in p2.split(os.sep)])

Upvotes: 3

user395760
user395760

Reputation:

When os.path.join encounters an absolute path, it throws away what it has accumulated to far. An absolute string is one that starts with a slash (ans on windows, with an optional drive letter). normpath won't touch that slash as it has the same notion of absolute paths. You have to strip that slash.

And if I may ask: where does it come from in the first place?

Upvotes: 11

Hugh Bothwell
Hugh Bothwell

Reputation: 56624

p1 is an absolute path (starts with \) - thus it is returned by itself, per the documentation:

join(a, *p)
    Join two or more pathname components, inserting "\" as needed.
    If any component is an absolute path, all previous path components
    will be discarded.

Upvotes: 4

Related Questions