99

I wanted to know what is the pythonic function for this :

I want to remove everything before the wa path.

p = path.split('/')
counter = 0
while True:
    if p[counter] == 'wa':
        break
    counter += 1
path = '/'+'/'.join(p[counter:])

For instance, I want '/book/html/wa/foo/bar/' to become '/wa/foo/bar/'.

1
  • 8
    Fyi, when dealing with paths better use the split/join functions from the os.path module Commented Jan 1, 2012 at 12:34

5 Answers 5

242

A better answer would be to use os.path.relpath:

http://docs.python.org/3/library/os.path.html#os.path.relpath

>>> import os
>>> full_path = '/book/html/wa/foo/bar/'
>>> relative_path = '/book/html'
>>> print(os.path.relpath(full_path, relative_path))
'wa/foo/bar'
2
  • 12
    This is a much better answer because it avoids any issues with different path separators. Commented Sep 18, 2015 at 22:59
  • 1
    Totally agree with @intrepidhero's comment, plus this works whether or not full_path contains the trailing / character or not—so it's even more general than that.
    – martineau
    Commented Dec 10, 2018 at 10:50
42

For Python 3.4+, you should use pathlib.PurePath.relative_to. From the documentation:

>>> p = PurePosixPath('/etc/passwd')
>>> p.relative_to('/')
PurePosixPath('etc/passwd')

>>> p.relative_to('/etc')
PurePosixPath('passwd')

>>> p.relative_to('/usr')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "pathlib.py", line 694, in relative_to
    .format(str(self), str(formatted)))
ValueError: '/etc/passwd' does not start with '/usr'

Also see this StackOverflow question for more answers to your question.

1
  • 1
    While the pathlib module is very "user friendly", it wasn't created until very late in the game. Personally I still prefer using os.path.relpath() as shown in the accepted answer because it will work in most versions of Python (including Python 2).
    – martineau
    Commented Dec 10, 2018 at 10:45
27
>>> path = '/book/html/wa/foo/bar/'
>>> path[path.find('/wa'):]
'/wa/foo/bar/'
4
  • +1: compared to using a regular expression, this is simpler, and probably about as fast. Commented Jan 1, 2012 at 12:23
  • 2
    This returns the last character if the string doesn't contain /wa (path[-1:]), so if that might happen you'd want to check if "/wa" in path first
    – dbr
    Commented Jan 1, 2012 at 12:50
  • 4
    alternately, you can use str.index instead of str.find to raise an exception when the needle is not in the haystack. Commented Jan 1, 2012 at 14:27
  • 2
    This doesn't work with multiple folders of same names.
    – nn0p
    Commented Jun 15, 2017 at 15:09
0
import re

path = '/book/html/wa/foo/bar/'
m = re.match(r'.*(/wa/[a-z/]+)',path)
print m.group(1)
1
  • This helps for my second question which was how to remove the last path if it is a integer. Nice :)
    – Natim
    Commented Jan 1, 2012 at 12:32
0

There is a new string functions called .removeprefix and .removesuffix in Python 3.9 and later.

https://peps.python.org/pep-0616/

These built-in functions behave like the following

def removeprefix(self: str, prefix: str, /) -> str:
    if self.startswith(prefix):
        return self[len(prefix):]
    else:
        return self[:]

def removesuffix(self: str, suffix: str, /) -> str:
    # suffix='' should not call self[:-0].
    if suffix and self.endswith(suffix):
        return self[:-len(suffix)]
    else:
        return self[:]

this does not directly remove it per the question but if you know the full prefix it can be a help.

Not the answer you're looking for? Browse other questions tagged or ask your own question.