Adding another suffix to a path that already has a suffix with pathlib

PythonPython 3.xPathlib

Python Problem Overview


I was converting some old Python code to use pathlib instead of os.path for most path-related operations, but I ended up with the following problem: I needed to add another extension to a path that already had an extension (not replace it). With os.path, since we are merely manipulating strings, the solution was to add the extension with string operations:

newpath = path + '.res'

It doesn't work with pathlib.Path because it doesn't allow concatenation of arbitrary characters. The closest I could find was the following:

newpath = path.with_suffix(path.suffix + '.res')

It looks like a workaround because it still uses string addition in the end. And it has a new pitfall because I forgot at first to handle the case where there are already several extensions and you want to add a new one, leading to the following code to get back the old behaviour:

newpath = path.with_suffix(''.join(path.suffixes) + '.res')

Now it doesn't feel terse nor clean since it uses more and more string operations to achieve the old behaviour instead of pure path operations. The fact that Path.suffixes exists means that the library's developers considered the case where a file can have multiple extensions, yet I couldn't find a way to simply add a new extension to a path. Is there a more idiomatic way that I have missed to achieve the same behaviour?

EDIT: actually path.with_suffix(path.suffix + '.res') is enough to handle the case where there are already several file extensions, even though it wasn't immeditely obvious to me.

Python Solutions


Solution 1 - Python

I find the following slightly more satisfying than the answers that have already been given:

new_path = path.parent / (path.name + '.suffix')

Solution 2 - Python

It doesn't seem like Path's like being modified in-place (you can't change .parts[-1] directory or change .suffixes, etc.), but that doesn't mean you need to resort to anything too unsavory. The following works just fine, even if it's not quite as elegant as I'd like:

new_path = path.with_suffix(path.suffix + new_suffix)

where path is your original Path variable, and new_suffix is the string with your new suffix/extension (including the leading ".")

Solution 3 - Python

You can just convert your Path to string then add new extension and convert back to Path:

from pathlib import Path
first = Path("D:/user/file.xy")
print(first)
second = Path(str(first)+".res")
print(second)

Solution 4 - Python

You might use pathlib3x - it offers a backport of the latest (at the date of writing this answer Python 3.10.a0) Python pathlib for Python 3.6 or newer, and a few additional functions like append_suffix

>>> python -m pip install pathlib3x

>>> import pathlib3x as pathlib

>>> pathlib.Path('some_path').append_suffix('.ext')
PosixPath('some_path.ext')
>>> pathlib.Path('some_path.ext.ext2').append_suffix('.ext3')
PosixPath('some_path.ext.ext2.ext3')


you can find it on github or PyPi


Disclaimer: I'm the author of the pathlib3x library.

Solution 5 - Python

I think this would be better since you just want to extend the current path with an arbitrary string.

old_path = Path("/the/old/path.foo")  # "/the/old/path.foo"
new_path = Path(f"{old_path}.bar")    # "/the/old/path.foo.bar"

Solution 6 - Python

if you want to append the file name, but not change the extension, this works

matfile2 = pathlib.Path.joinpath(matfile.parent, matfile.stem+' insert'+matfile.suffix)

Solution 7 - Python

The following code should do what you want it to in a very dynamic way.

from pathlib import Path
import time

p = Path('.')
p = p / '..' / 'Python' / 'Files' / 'Texts_to_read' / 'a_text_file'

new_p = str(p).split('\\')

new_suffix = '.txt'

new_p[-1] = new_p[-1] + new_suffix

p = Path('.')

for x in new_p:
    p = p / x

print(new_p)

print(p)
print(str(p))

time.sleep(5)

The fact that normal string operations can be used in this case is a good thing, as it adds a great deal of control over the file path desired without requiring a large assortment of new functions.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMorwennView Question on Stackoverflow
Solution 1 - PythonP-GnView Answer on Stackoverflow
Solution 2 - PythonscnerdView Answer on Stackoverflow
Solution 3 - PythonWinandView Answer on Stackoverflow
Solution 4 - PythonbitranoxView Answer on Stackoverflow
Solution 5 - PythonVicente Olivert RieraView Answer on Stackoverflow
Solution 6 - PythonnagordonView Answer on Stackoverflow
Solution 7 - PythonS. MansfieldView Answer on Stackoverflow