4

I have looked on Stack Overflow everywhere but I cant find a solution to this problem.

Given that I have a folder/file as string: "/path1/path2/path3/file" how can I get the parent folder and its parent folder. In other words if I want to traverse up one level "/path1/path2/path3" or two levels "/path1/path2" how can I get those string values from the original string path in python?

Please note that I don't simply want the pieces of the path (in other words not a list of ['path1', 'path2', 'path3']) but instead "/path1/path2/path3".

RFV
  • 831
  • 8
  • 22
  • 2
    Possible duplicate of [How to split a dos path into its components in Python](http://stackoverflow.com/questions/3167154/how-to-split-a-dos-path-into-its-components-in-python) – RedX Oct 06 '16 at 11:26
  • `os.path.realpath(__file__)` will give you string that contains path to your file, and then just apply string manipulation to shorten it. – zipa Oct 06 '16 at 11:28
  • 2
    [`os.path.dirname`](https://docs.python.org/3.6/library/os.path.html#os.path.dirname)? and apply it `n` times to go up `n` levels... – Bakuriu Oct 06 '16 at 11:51
  • No, "this is not what [he] asked for". Lol... – S. de Melo Oct 06 '16 at 11:58

6 Answers6

6

os.path.dirname() (doc) is the way to go. It returns the directory which contains the object pointed by the path:

>>> import os.path
>>> os.path.dirname('/path1/path2/path3/file')
'/path1/path2/path3'

In this case, you want the "grandparent" directory, so just use the function twice:

>>> parent = os.path.dirname('/path1/path2/path3/file')
>>> os.path.dirname(parent)
'/path1/path2'

If you want to do it an arbitrary number of times, a function can be helpful here:

def go_up(path, n):
    for i in range(n):
        path = os.path.dirname(path)

    return path

Here are some examples:

>>> go_up('/path1/path2/path3/file', 1)
'/path1/path2/path3'
>>> go_up('/path1/path2/path3/file', 2)
'/path1/path2'
>>> go_up('/path1/path2/path3/file', 3)
'/path1'
brandizzi
  • 26,083
  • 8
  • 103
  • 158
5

You can use the pathlib module:

>>> path = pathlib.PurePath('/file1/file2/file3/file')
>>> path.parts
('/', 'file1', 'file2', 'file3', 'file')
>>> os.path.join(*path.parts[:-2])
'/file1/file2'

So just put path.parts[:-n] for n levels up.

Alternatively you can use the parents attribute:

>>> path = pathlib.PurePath('/file1/file2/file3/file4/file5/file6')
>>> path.parents[0]
PurePosixPath('/file1/file2/file3/file4/file5')
>>> path.parents[1]
PurePosixPath('/file1/file2/file3/file4')
>>> path.parents[4]
PurePosixPath('/file1')

So to go up n levels just use parents[n-1].

To convert a *Path object to a string just call str on it:

>>> str(path)
'/file1/file2/file3/file4/file5/file6'
Bakuriu
  • 98,325
  • 22
  • 197
  • 231
4

additionally to all other answers, you can also use os.path.join function with the os.path.pardir variable which usually equals ...

>>> path = "some/random/path/to/process"
>>> parent = os.path.pardir
>>> grand_parent_path = os.path.join(path, parent, parent)
>>> grand_parent_path
'some/random/path/to/process\\..\\..'

If you don't want to repeat parent several times, you can use a multipled list:

>>> os.path.join(path, *([parent] * 3))
'some/random/path/to/process\\..\\..\\..'

The result is quite ugly, so you can use the os.path.normpath function to make it prettier:

>>> os.path.normpath(os.path.join(path, *([parent] * 3)))
'some\\random'

Important note: Doing so, you are sure your code is portable

Tryph
  • 5,946
  • 28
  • 49
1

os.path.split will do it for you. There are many other interesting functions in there.

RedX
  • 14,749
  • 1
  • 53
  • 76
  • Split the pathname path into a pair, (head, tail) where tail is the last pathname component and head is everything leading up to that. How can I traverve two or 3 levels up? – RFV Oct 06 '16 at 11:28
  • 1
    @RFVenter Call the function multiple times on the result? – RedX Oct 06 '16 at 11:29
0
'/'.join (originalPath.split ('/') [:-2])

It will take you 2 levels up.

brandizzi
  • 26,083
  • 8
  • 103
  • 158
Jacques de Hooge
  • 6,750
  • 2
  • 28
  • 45
  • 1
    This may fail, for example, if the path is a Windows path using `\` as separator. – brandizzi Oct 06 '16 at 11:32
  • Yes, but the question was about a Linux path. By the way, as a habit I always convert paths to Linux paths. But admitted, os.path is the generally accepted toolbox for the job. I like a small toolbox, though, sometimes I can't find the hammer anymore... – Jacques de Hooge Oct 06 '16 at 11:35
  • 1
    It can be resolved by replacing '/' by `os.path.sep` – S. de Melo Oct 06 '16 at 11:42
  • @JacquesdeHooge I agree, the string is specific and your answer is nice, obvious (duh) and concise. Thank you – RFV Oct 06 '16 at 11:46
0

os.path.dirname gives you the parent directory.

S. de Melo
  • 786
  • 4
  • 11