How to replace (or strip) an extension from a filename in Python?

Posted on

Question :

How to replace (or strip) an extension from a filename in Python?

Is there a built-in function in Python that would replace (or remove, whatever) the extension of a filename (if it has one) ?

Example:

print replace_extension('/home/user/somefile.txt', '.jpg')

In my example: /home/user/somefile.txt would become /home/user/somefile.jpg

I don’t know if it matters, but I need this for a SCons module I’m writing. (So perhaps there is some SCons specific function I can use ?)

I’d like something clean. Doing a simple string replacement of all occurrences of .txt within the string is obviously not clean. (This would fail if my filename is somefile.txt.txt.txt)

Asked By: ereOn

||

Answer #1:

Try os.path.splitext it should do what you want.

import os
print os.path.splitext('/home/user/somefile.txt')[0]+'.jpg'
Answered By: jethro

Answer #2:

Expanding on AnaPana’s answer, how to remove an extension using pathlib (Python >= 3.4):

>>> from pathlib import Path

>>> filename = Path('/some/path/somefile.txt')

>>> filename_wo_ext = filename.with_suffix('')

>>> filename_replace_ext = filename.with_suffix('.jpg')

>>> print(filename)
/some/path/somefile.ext    

>>> print(filename_wo_ext)
/some/path/somefile

>>> print(filename_replace_ext)
/some/path/somefile.jpg
Answered By: JS.

Answer #3:

As @jethro said, splitext is the neat way to do it. But in this case, it’s pretty easy to split it yourself, since the extension must be the part of the filename coming after the final period:

filename = '/home/user/somefile.txt'
print( filename.rsplit( ".", 1 )[ 0 ] )
# '/home/user/somefile'

The rsplit tells Python to perform the string splits starting from the right of the string, and the 1 says to perform at most one split (so that e.g. 'foo.bar.baz' -> [ 'foo.bar', 'baz' ]). Since rsplit will always return a non-empty array, we may safely index 0 into it to get the filename minus the extension.

Answered By: Katriel

Answer #4:

I prefer the following one-liner approach using str.rsplit():

my_filename.rsplit('.', 1)[0] + '.jpg'

Example:

>>> my_filename = '/home/user/somefile.txt'
>>> my_filename.rsplit('.', 1)
>>> ['/home/user/somefile', 'txt']
Answered By: IvanD

Answer #5:

Another way to do is to use the str.rpartition(sep) method.

For example:

filename = '/home/user/somefile.txt'
(prefix, sep, suffix) = filename.rpartition('.')

new_filename = prefix + '.jpg'

print new_filename
Answered By: user2802945

Answer #6:

For Python >= 3.4:

from pathlib import Path

filename = '/home/user/somefile.txt'

p = Path(filename)
new_filename = p.parent.joinpath(p.stem + '.jpg') # PosixPath('/home/user/somefile.jpg')
new_filename_str = str(new_filename) # '/home/user/somefile.jpg'
Answered By: AnaPana

Answer #7:

Handling multiple extensions

In the case where you have multiple extensions this one-liner using pathlib and str.replace works a treat:

Remove/strip extensions

>>> from pathlib import Path
>>> p = Path("/path/to/myfile.tar.gz")
>>> extensions = "".join(p.suffixes)

# any python version
>>> str(p).replace(extensions, "")
'/path/to/myfile'

# python>=3.9
>>> str(p).removesuffix(extensions)
'/path/to/myfile'

Replace extensions

>>> p = Path("/path/to/myfile.tar.gz")
>>> extensions = "".join(p.suffixes)
>>> new_ext = ".jpg"
>>> str(p).replace(extensions, new_ext)
'/path/to/myfile.jpg'

If you also want a pathlib object output then you can obviously wrap the line in Path()

>>> Path(str(p).replace("".join(p.suffixes), ""))
PosixPath('/path/to/myfile')

Wrapping it all up in a function

from pathlib import Path
from typing import Union

PathLike = Union[str, Path]


def replace_ext(path: PathLike, new_ext: str = "") -> Path:
    extensions = "".join(Path(path).suffixes)
    return Path(str(p).replace(extensions, new_ext))


p = Path("/path/to/myfile.tar.gz")
new_ext = ".jpg"

assert replace_ext(p, new_ext) == Path('/path/to/myfile.jpg')
assert replace_ext(str(p), new_ext) == Path('/path/to/myfile.jpg')
assert replace_ext(p) == Path('/path/to/myfile')
    
Answered By: Michael Hall

Leave a Reply

Your email address will not be published. Required fields are marked *