132

Suppose from index.py with CGI, I have post file foo.fasta to display file. I want to change foo.fasta's file extension to be foo.aln in display file. How can I do it?

cs95
  • 379,657
  • 97
  • 704
  • 746
MysticCodes
  • 3,092
  • 5
  • 25
  • 33
  • 1
    Does this answer your question? [How to replace (or strip) an extension from a filename in Python?](https://stackoverflow.com/questions/3548673/how-to-replace-or-strip-an-extension-from-a-filename-in-python) – Tomerikoo May 26 '21 at 14:27

9 Answers9

131

An elegant way using pathlib.Path:

from pathlib import Path
p = Path('mysequence.fasta')
p.rename(p.with_suffix('.aln'))
Jean-François Corbett
  • 37,420
  • 30
  • 139
  • 188
Nikita Malyavin
  • 1,868
  • 1
  • 12
  • 10
  • 4
    Although the OP didn't ask to perform a rename, it was in the tags, and if you're going to perform a rename and if it's possible the input might have a path and not just a filename, this technique is the right one. – Jason R. Coombs Feb 11 '18 at 15:51
  • 7
    Regarding `.with_suffix()`, the properties `.suffix` and `.suffixes` should have setters. – Polv Jul 16 '18 at 06:50
  • Oddly enough, it seems like `.suffix` is read-only, at least as of 3.9.5. – Jesse May 13 '22 at 22:46
  • 1
    @Jesse Paths are immutable https://docs.python.org/3/library/pathlib.html#general-properties – Nikita Malyavin May 17 '22 at 15:25
106

os.path.splitext(), os.rename()

for example:

# renamee is the file getting renamed, pre is the part of file name before extension and ext is current extension
pre, ext = os.path.splitext(renamee)
os.rename(renamee, pre + new_extension)
RinkyPinku
  • 410
  • 3
  • 20
Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
  • Can you be more specific, i saw documentation before too but didn't work. – MysticCodes May 24 '10 at 21:17
  • Use the first function to get the base. Combine it with the new extension and pass the old filename and the new filename to the second function. – Ignacio Vazquez-Abrams May 24 '10 at 21:20
  • 5
    actually, its better to use this method instead for python3: pathlib.path(pathtofile).with_suffix(".mynewext"). The way, suggested with pathlib.path(pathtofile).stem works but will delete the path before the basename. – Bimo Aug 17 '17 at 15:59
  • 4
    str(pathlib.path(pathtofile).with_suffix(".mynewext")) – Bimo Aug 17 '17 at 16:13
  • There's no real need for assigning a variable to the original extension. I find this is more straightforward: os.rename(filename, os.path.splitext(filename)[0] + '.aln') – PYB Dec 30 '20 at 22:22
85
import os
thisFile = "mysequence.fasta"
base = os.path.splitext(thisFile)[0]
os.rename(thisFile, base + ".aln")

Where thisFile = the absolute path of the file you are changing

amarillion
  • 24,487
  • 15
  • 68
  • 80
FryDay
  • 1,047
  • 1
  • 7
  • 10
27

Starting from Python 3.4 there's pathlib built-in library. So the code could be something like:

from pathlib import Path

filename = "mysequence.fasta"
new_filename = Path(filename).stem + ".aln"

https://docs.python.org/3.4/library/pathlib.html#pathlib.PurePath.stem

I love pathlib :)

AnaPana
  • 1,958
  • 19
  • 18
  • 3
    This is even better with python 3.6 string interpolation syntax ( https://www.python.org/dev/peps/pep-0498/ ) `new_filename = f"{Path(filename).stem}.aln"` – Kishan B Feb 03 '18 at 07:11
  • 4
    Be careful - stem also strips the path if one is present. If you wanted to rename the file and if a path was supplied (which admittedly it wasn't in the question), this technique would fail. – Jason R. Coombs Feb 11 '18 at 15:49
  • 8
    Also, the result is a string, no longer a pathlib Path. `p.parent / (p.stem + '.aln')` will give you a new Path. – eric.frederich Feb 17 '18 at 03:12
  • 5
    Warning: Path(filename).stem drops the directory (prefix) part of the filename. – user1741137 Dec 04 '19 at 11:00
22

Use this:

os.path.splitext("name.fasta")[0]+".aln"

And here is how the above works:

The splitext method separates the name from the extension creating a tuple:

os.path.splitext("name.fasta")

the created tuple now contains the strings "name" and "fasta". Then you need to access only the string "name" which is the first element of the tuple:

os.path.splitext("name.fasta")[0]

And then you want to add a new extension to that name:

os.path.splitext("name.fasta")[0]+".aln"
multigoodverse
  • 7,638
  • 19
  • 64
  • 106
10

As AnaPana mentioned pathlib is more new and easier in python 3.4 and there is new with_suffix method that can handle this problem easily:

from pathlib import Path
new_filename = Path(mysequence.fasta).with_suffix('.aln')
Mahdi Saravi
  • 101
  • 1
  • 4
3

Using pathlib and preserving full path:

from pathlib import Path
p = Path('/User/my/path')
new_p = Path(p.parent.as_posix() + '/' + p.stem + '.aln')
PollPenn
  • 723
  • 2
  • 8
  • 18
3

Sadly, I experienced a case of multiple dots on file name that splittext does not worked well... my work around:

file = r'C:\Docs\file.2020.1.1.xls'
ext = '.'+ os.path.realpath(file).split('.')[-1:][0]
filefinal = file.replace(ext,'')
filefinal = file + '.zip'
os.rename(file ,filefinal)
Hugo Vares
  • 977
  • 7
  • 7
1
>> file = r'C:\Docs\file.2020.1.1.xls'
>> ext = '.'+ os.path.realpath(file).split('.')[-1:][0]
>> filefinal = file.replace(ext,'.zip')
>> os.rename(file ,filefinal) 

Bad logic for repeating extension, sample: 'C:\Docs\.xls_aaa.xls.xls'

uDev
  • 31
  • 3