62

Is it possible to use the python command rstrip so that it does only remove one exact string and does not take all letters separately?

I was confused when this happened:

>>>"Boat.txt".rstrip(".txt")
>>>'Boa'

What I expected was:

>>>"Boat.txt".rstrip(".txt")
>>>'Boat'

Can I somehow use rstrip and respect the order, so that I get the second outcome?

aldorado
  • 4,394
  • 10
  • 35
  • 46
  • 7
    `rstrip` is the wrong method because it will look at `".txt"`, and understand it as something like `['.', 't', 'x', 't']` aka "keep removing characters that matches those in that list until you reach a character that is not in that list. – neverendingqs Jul 22 '15 at 15:06

7 Answers7

60

You're using wrong method. Use str.replace instead:

>>> "Boat.txt".replace(".txt", "")
'Boat'

NOTE: str.replace will replace anywhere in the string.

>>> "Boat.txt.txt".replace(".txt", "")
'Boat'

To remove the last trailing .txt only, you can use regular expression:

>>> import re
>>> re.sub(r"\.txt$", "", "Boat.txt.txt")
'Boat.txt'

If you want filename without extension, os.path.splitext is more appropriate:

>>> os.path.splitext("Boat.txt")
('Boat', '.txt')
falsetru
  • 357,413
  • 63
  • 732
  • 636
41

Starting with Python 3.9, use .removesuffix():

"Boat.txt".removesuffix(".txt")

On earlier versions of Python, you'll have to either define it yourself:

def removesuffix(s, suf):
    if suf and s.endswith(suf):
        return s[:-len(suf)]
    return s

(you need to check that suf isn't empty, otherwise removing an empty suffix e.g. removesuffix("boat", "") will do return s[:0] and return "" instead of "boat")

or use regex:

import re
suffix = ".txt"
s = re.sub(re.escape(suffix) + '$', '', s)
Boris Verkhovskiy
  • 14,854
  • 11
  • 100
  • 103
nneonneo
  • 171,345
  • 36
  • 312
  • 383
  • 2
    This `strip_suffix(s, suf)` solution is the best answer here, as the accepted solution with `.replace()` is replacing one slightly dangerous solution to the with another slightly dangerous solution. Both the original `.rstrip` and `.replace` are liable to occasionally return results contrary to the original intent of the OP. I wonder why Python does not have something like this built in.. – cardamom Apr 01 '19 at 12:32
  • Minor improvment: `len(s)` can be dropped, a negative offset is sufficient. – guidot Aug 12 '20 at 15:32
  • 1
    If you look at the edit history, I originally used only a negative offset. However, it was edited by @wim to include len(s) in order to make it work in the case where the suffix is empty. I agree with this change - it would subtly truncate the entire string with an empty suffix which would be quite unexpected behaviour (even if an empty suffix isn’t something you’d usually use). – nneonneo Aug 12 '20 at 15:55
  • @guidot Actually, if you remove `len(s)` in the splicing (i.e. `return s[:-len(suf)]`), passing an empty suffix (`suf=''`) will result in an empty return value! You would have to check that the suffix is not empty (i.e. `if suf and s.endswith(suf)`). – TedGrassman Nov 05 '20 at 14:39
  • Woops, @nneonneo already addressed the empty suffix case ^^ Anyway, it's worth pointing out because I too thought I was optimizing the function by removing `len(s)` and using a negative offset, only to encounter a bug much later due to empty suffix resulting in a empty return string! – TedGrassman Nov 05 '20 at 14:53
13

In Python 3.9, as part of PEP-616, you can now use the removeprefix and removesuffix functions:

>>> "Boat.txt".removeprefix("Boat")
>>> '.txt'

>>> "Boat.txt".removesuffix(".txt")
>>> 'Boat'
Pikamander2
  • 7,332
  • 3
  • 48
  • 69
nneonneo
  • 171,345
  • 36
  • 312
  • 383
1
>>> foo="Boat.txt"
>>> foo[:foo.rfind(".txt")]
'Boat'
0
>>> myfile = "file.txt"
>>> t = ""
>>> for i in myfile:
...     if i != ".":
...             t+=i
...     else:
...             break
... 
>>> t
'file'
>>> # Or You can do this
>>> import collections
>>> d = collections.deque("file.txt")
>>> while True:
...     try:
...             if "." in t:
...                     break
...             t+=d.popleft()
...     except IndexError:
...             break
...     finally:
...             filename = t[:-1]
... 
>>> filename
'file'
>>> 
Th3carpenter
  • 201
  • 1
  • 4
  • 16
0

This will work regardless of extension type.

# Find the rightmost period character
filename = "my file 1234.txt"

file_extension_position = filename.rindex(".")

# Substring the filename from first char up until the final period position
stripped_filename = filename[0:file_extension_position]
print("Stripped Filename: {}".format(stripped_filename))
0

In addition to the other excellent answers, sometimes rpartiton may also get you there (depends on the exact usecase).

>> "Boat.txt".rpartition('.txt')
('Boat', '.txt', '')

>> "Boat.txt".rpartition('.txt')[0]
'Boat'
Xaser
  • 2,066
  • 2
  • 22
  • 45