How to get only the last part of a path in Python?
Asked Answered
H

10

400

In , suppose I have a path like this:

/folderA/folderB/folderC/folderD/

How can I get just the folderD part?

Hieronymus answered 13/10, 2010 at 15:3 Comment(1)
path.split('/')[len(path.split('/'))-1:][0]Sanatorium
B
618

Use os.path.normpath to strip off any trailing slashes, then os.path.basename gives you the last part of the path:

>>> os.path.basename(os.path.normpath('/folderA/folderB/folderC/folderD/'))
'folderD'

Using only basename gives everything after the last slash, which in this case is ''.

Biparty answered 13/10, 2010 at 15:8 Comment(4)
I initially thought rstrip('/') would be simpler but then quickly realised I'd have to use rstrip(os.path.sep), so obviously the use of normpath is justified.Ken
This doesn't seem to work on Windows long paths, e.g., '\\\\?\\D:\\A\\B\\C\\' and '\\\\?\\UNC\\svr\\B\\C\\' (returns an empty string) This solution works for all cases.Imidazole
@jinnlao's answer is much much better nowadays.Clarenceclarenceux
I'd add str.strip around it, too, because based on input, you might have whitespaces, but that might just be meAirel
R
129

With python 3 you can use the pathlib module (pathlib.PurePath for example):

>>> import pathlib

>>> path = pathlib.PurePath('/folderA/folderB/folderC/folderD/')
>>> path.name
'folderD'

If you want the last folder name where a file is located:

>>> path = pathlib.PurePath('/folderA/folderB/folderC/folderD/file.py')
>>> path.parent.name
'folderD'
Rigby answered 25/2, 2019 at 14:47 Comment(2)
well, just to point it out PurePath vs Path, the first provides "purely computational operations" (no I/O), while the other ("concrete path") inherits from the first but also provides I/O operations.Alberich
@Alberich To expand on this, this answer applies to non-pure paths as wellDustup
W
39

You could do

>>> import os
>>> os.path.basename('/folderA/folderB/folderC/folderD')

UPDATE1: This approach works in case you give it /folderA/folderB/folderC/folderD/xx.py. This gives xx.py as the basename. Which is not what you want I guess. So you could do this -

>>> import os
>>> path = "/folderA/folderB/folderC/folderD"
>>> if os.path.isdir(path):
        dirname = os.path.basename(path)

UPDATE2: As lars pointed out, making changes so as to accomodate trailing '/'.

>>> from os.path import normpath, basename
>>> basename(normpath('/folderA/folderB/folderC/folderD/'))
'folderD'
Woodchopper answered 13/10, 2010 at 15:5 Comment(4)
In Python-think, os.path.basename(".../") correctly yields ''. Yes, I, too, find that sub-optimal. The ...basename(...normpath... solution below is canonical, though.Snowinsummer
@lars yeah! just saw that in that case normalize the path first before feeding it to basename. os.path.basename(os.path.normpath('/folderA/folderB/folderC/folderD/'))Woodchopper
UPDATE2 is the best approach I have found so far.Lamonica
thumbs up for the UPDATE2Aretta
R
27

Here is my approach:

>>> import os
>>> print os.path.basename(
        os.path.dirname('/folderA/folderB/folderC/folderD/test.py'))
folderD
>>> print os.path.basename(
        os.path.dirname('/folderA/folderB/folderC/folderD/'))
folderD
>>> print os.path.basename(
        os.path.dirname('/folderA/folderB/folderC/folderD'))
folderC
Renz answered 3/7, 2017 at 10:40 Comment(2)
What does your approach solve different/better than the aforementioned?Nurse
@user1767754: though terse, this does illustrate a solution that works with our without a file name, while also showing the pitfall if a final directory does not have a trailing / (and without needing purepath)Marketa
N
11

I was searching for a solution to get the last foldername where the file is located, I just used split two times, to get the right part. It's not the question but google transfered me here.

pathname = "/folderA/folderB/folderC/folderD/filename.py"
head, tail = os.path.split(os.path.split(pathname)[0])
print(head + "   "  + tail)
Nurse answered 10/12, 2014 at 21:57 Comment(1)
You can also use os.path.basename(os.path.dirname(pathname)) which would give folderD in your example. See answer from @Mike MitererMarketa
Q
9

If you use the native python package pathlib it's really simple.

>>> from pathlib import Path
>>> your_path = Path("/folderA/folderB/folderC/folderD/")
>>> your_path.stem
'folderD'

Suppose you have the path to a file in folderD.

>>> from pathlib import Path
>>> your_path = Path("/folderA/folderB/folderC/folderD/file.txt")
>>> your_path.name
'file.txt'
>>> your_path.parent.name
'folderD'
Quarry answered 5/7, 2021 at 14:29 Comment(3)
In your 2nd example stem will only return file not file.txt. If you want file.txt you need your_path.name. Pathlib DocsIndustrialize
Should be your_path.parent.name that gives "folderD"Levin
Actually, it was the result which was wrong since it was meant as an example of what the output would look like, but for clarity's sake, I like your suggestion better.Quarry
C
8

I like the parts method of Path for this:

grandparent_directory, parent_directory, filename = Path(export_filename).parts[-3:]
log.info(f'{t: <30}: {num_rows: >7} Rows exported to {grandparent_directory}/{parent_directory}/{filename}')
Corabella answered 17/10, 2019 at 17:22 Comment(1)
My favorite, even cleaner: '/'.join(Path(export_filename).parts[-3:])Tadich
U
0

During my current projects, I'm often passing rear parts of a path to a function and therefore use the Path module. To get the n-th part in reverse order, I'm using:

from typing import Union
from pathlib import Path

def get_single_subpath_part(base_dir: Union[Path, str], n:int) -> str:
    if n ==0:
        return Path(base_dir).name
    for _ in range(n):
        base_dir = Path(base_dir).parent
    return getattr(base_dir, "name")

path= "/folderA/folderB/folderC/folderD/"

# for getting the last part:
print(get_single_subpath_part(path, 0))
# yields "folderD"

# for the second last
print(get_single_subpath_part(path, 1))
#yields "folderC"

Furthermore, to pass the n-th part in reverse order of a path containing the remaining path, I use:

from typing import Union
from pathlib import Path

def get_n_last_subparts_path(base_dir: Union[Path, str], n:int) -> Path:
    return Path(*Path(base_dir).parts[-n-1:])

path= "/folderA/folderB/folderC/folderD/"

# for getting the last part:
print(get_n_last_subparts_path(path, 0))
# yields a `Path` object of "folderD"

# for second last and last part together 
print(get_n_last_subparts_path(path, 1))
# yields a `Path` object of "folderc/folderD"

Note that this function returns a Pathobject which can easily be converted to a string (e.g. str(path))

Urbanize answered 16/10, 2020 at 16:57 Comment(0)
F
-4
path = "/folderA/folderB/folderC/folderD/"
last = path.split('/').pop()
Flamen answered 13/10, 2010 at 15:6 Comment(2)
Seriously, use the os.path module.Brilliantine
Do people try their answers before posting?Aretta
E
-7
str = "/folderA/folderB/folderC/folderD/"
print str.split("/")[-2]
Edelmiraedelson answered 13/10, 2010 at 15:6 Comment(3)
he wants folderD. not folderCWoodchopper
It gives "folderD" because the trailing slash makes the final item in the list be ""Secrete
Seriously, use the os.path module.Brilliantine

© 2022 - 2024 — McMap. All rights reserved.