4

I can't find an effective way to do this. The best way to describe what I'm trying to do is by example, so where we go (assuming /bar/ is the parent):

C:\foo\bar\baz\text.txt

will be my path. I'm interested in everything up to the top-level parent directory of the path. What I need is a script that will do just that. In other words, I want to only grab the

\bar\baz\text.txt

Split doesn't work for me. It will split the file and the path, but it won't give the output like this. Is there an inbuilt function I'm missing or am I SOL? Thanks!

Manuel Allenspach
  • 12,467
  • 14
  • 54
  • 76
Dr.McNinja
  • 455
  • 1
  • 6
  • 15

7 Answers7

1

I created a helper function that does the job:

import os
def get_path_tail(path, tail_length = 1):
    assert isinstance(tail_length, int)
    if tail_length == 1:
        return path.split('/')[-tail_length]
    elif tail_length > 1:
        return os.path.join(*path.split('/')[-tail_length:])

Behaviour:

>>> path = os.path.join('C:','foo','bar', 'baz','text.txt')
>>> print get_path_tail(path, tail_length = 3)

    bar/baz/text.txt

Its signature is like that in the answer of ForeverWintr, but I couldn't comment on his answer as I don't have enough reputation yet. :)

King Thrushbeard
  • 869
  • 10
  • 16
Yohan Grember
  • 587
  • 5
  • 13
1

You could always use string.split():

>>> print '\\' + path.split('\\', 2)[-1]
\bar\baz\text.txt
Zach Kelling
  • 52,505
  • 13
  • 109
  • 108
1

I'm not sure what you mean when you say "top-level parent directory". Your top-level directory is C:\. Parent of what? If you're trying to get a relative path that starts with the parent of your current working directory, try this:

import os.path
os.path.relpath("C:\\foo\\bar\\baz\\text.txt", os.path.dirname(os.path.realpath('..')))
ʇsәɹoɈ
  • 22,757
  • 7
  • 55
  • 61
1

Not sure what you want, but you may be able to use the little known rsplit, which splits from the right side of the string.

>>> filepath = r"C:\foo\bar\baz\text.txt"
>>> directories_deep = 3
>>> os.path.sep.join(filepath.rsplit(os.path.sep, directories_deep)[-directories_deep:])
'bar\\baz\\text.txt'
monkut
  • 42,176
  • 24
  • 124
  • 155
0

Here's how I solved this problem:

def gettail(path_, length):        
    elements = []
    for i in range(length):
        s = os.path.split(path_)
        elements.append(s[1])
        path_ = s[0] 

    outpath = elements.pop()
    while elements:
        outpath = os.path.join(outpath, elements.pop())
    return outpath

Output:

>>> print gettail(r"C:\foo\bar\baz\text.txt", 3)
    'bar\\baz\\text.txt'

Suggestions/improvements welcome.

ForeverWintr
  • 5,492
  • 2
  • 36
  • 65
0
In [44]: path = 'a/b/c'

In [45]: back = os.path.relpath('.', os.path.join(path, '..'))

In [46]: back
Out[46]: '..\\..'

In [47]: tail = os.path.relpath(path, os.path.join(path, back)))

In [48]: tail
Out[48]: 'b\\c'

Aka no not that I know of.

Owen
  • 38,836
  • 14
  • 95
  • 125
0

I would keep it simple. Convert both cwd and your input path into absolute paths and then just use startswith and slicing

path = os.path.abspath(path)
#Make sure you finish curDir with a path separator
#to avoid incorrect partial matches
curDir = os.path.abspath(".") + os.path.sep
if path.startswith(curDir):
    whatYouWant = path[len(curDir) - 1:]
Peter Lyons
  • 142,938
  • 30
  • 279
  • 274