382

In , suppose I have a path like this:

/folderA/folderB/folderC/folderD/

How can I get just the folderD part?

Innat
  • 16,113
  • 6
  • 53
  • 101
pepero
  • 7,095
  • 7
  • 41
  • 72

10 Answers10

598

Use os.path.normpath, then os.path.basename:

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

The first strips off any trailing slashes, the second gives you the last part of the path. Using only basename gives everything after the last slash, which in this case is ''.

Fred Foo
  • 355,277
  • 75
  • 744
  • 836
  • 2
    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. – Erik Kaplun Jun 29 '14 at 13:44
  • 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](https://stackoverflow.com/a/8384788/5659969) solution works for all cases. – omasoud Feb 07 '20 at 17:54
  • 1
    @jinnlao's [answer](https://stackoverflow.com/a/54868730/9835872) is much much better nowadays. – ruohola Jun 30 '21 at 13:18
  • I'd add `str.strip` around it, too, because based on input, you might have whitespaces, but that might just be me – IceFire Jan 09 '23 at 08:56
119

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'
jinnlao
  • 1,341
  • 1
  • 9
  • 6
  • 6
    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. – Paolo Dec 25 '20 at 17:14
  • 1
    @Paolo To expand on this, this answer applies to non-pure paths as well – Ted Brownlow Sep 10 '22 at 18:15
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'
Srikar Appalaraju
  • 71,928
  • 54
  • 216
  • 264
26

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
Mike Mitterer
  • 6,810
  • 4
  • 41
  • 62
  • 1
    What does your approach solve different/better than the aforementioned? – user1767754 Jan 16 '18 at 00:17
  • @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) – Bryan P Mar 19 '21 at 18:19
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)
Shaido
  • 27,497
  • 23
  • 70
  • 73
user1767754
  • 23,311
  • 18
  • 141
  • 164
  • 3
    You can also use `os.path.basename(os.path.dirname(pathname))` which would give `folderD` in your example. See answer from @Mike Miterer – Bryan P Mar 19 '21 at 18:17
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}')
Andrew Magerman
  • 1,394
  • 1
  • 13
  • 23
8

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'
CB Madsen
  • 582
  • 7
  • 8
  • 1
    In your 2nd example `stem` will only return `file` not `file.txt`. If you want `file.txt` you need `your_path.name`. [Pathlib Docs](https://docs.python.org/3/library/pathlib.html#pathlib.PurePath.stem) – Matthew Barlowe Mar 14 '22 at 15:28
  • 1
    Should be your_path.parent.name that gives "folderD" – The Unfun Cat May 09 '23 at 12:39
  • 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. – CB Madsen May 10 '23 at 16:03
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))

dheinz
  • 988
  • 10
  • 16
-4
path = "/folderA/folderB/folderC/folderD/"
last = path.split('/').pop()
GSto
  • 41,512
  • 37
  • 133
  • 184
-7
str = "/folderA/folderB/folderC/folderD/"
print str.split("/")[-2]
Andrew Sledge
  • 10,163
  • 2
  • 29
  • 30