Bagaimana cara mengganti (atau menghapus) ekstensi dari nama file dengan Python?

112

Apakah ada fungsi built-in dalam Python yang akan menggantikan (atau menghapus, apapun) ekstensi nama file (jika ada)?

Contoh:

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

Dalam contoh saya: /home/user/somefile.txtakan menjadi/home/user/somefile.jpg

Saya tidak tahu apakah itu penting, tetapi saya membutuhkan ini untuk modul SCons yang saya tulis. (Jadi mungkin ada beberapa fungsi khusus SCons yang dapat saya gunakan?)

Saya mau yang bersih . Melakukan penggantian string sederhana dari semua kejadian .txtdi dalam string jelas tidak bersih. (Ini akan gagal jika nama file saya somefile.txt.txt.txt)

ereOn
sumber
2
kemungkinan duplikat Mengekstrak ekstensi dari nama file dengan Python
S. Lott
SCons memungkinkan mendapatkan di basis file dalam string tindakan. Bisakah Anda memposting logika khusus scons Anda yang membutuhkan ini? Apakah ini untuk aksi, emitor, pemindai?
bdbaddog
beberapa di antaranya tampaknya tidak berfungsi lagi karena jalur mengembalikan PosixPath bukan string: p
shigeta

Jawaban:

146

Coba os.path.splitext itu harus melakukan apa yang Anda inginkan.

import os
print os.path.splitext('/home/user/somefile.txt')[0]+'.jpg'
jethro
sumber
15
@ S. Lott: Percaya atau tidak. Tapi saya lakukan. Aku selalu melakukan. Mungkin dengan istilah yang salah.
sebelum tanggal
@ereOn: Karena pertanyaan Anda menggunakan frasa yang hampir persis sama, saya sedikit terkejut Anda tidak menemukannya. Pertanyaan Anda terdiri dari 5 kata - berturut-turut - yang sama persis.
S. Lott
Hanya letakkan nama baru bersama dengan os.path.join agar terlihat bersih.
Tony Veijalainen
4
@Tony Veijalainen: Anda tidak boleh menggunakan os.path.join karena itu untuk menggabungkan komponen jalur dengan pemisah jalur khusus OS. Misalnya, print os.path.join(os.path.splitext('/home/user/somefile.txt')[0], '.jpg')akan kembali /home/user/somefile/.jpg, yang tidak diinginkan.
scottclowe
@ S. Lott - 99 orang memberikan suara atas jawaban ini dengan cukup jelas berarti posting ini bermanfaat, tidak perlu mempermalukan semua huruf besar
JeffThompson
91

Memperluas jawaban AnaPana, cara menghapus ekstensi menggunakan 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
JS.
sumber
1
Python asli memiliki penulisan contoh kasus penggunaan modul pathlib yang bagus
Steven
2
Jawaban ini adalah pendekatan khas saya, tetapi tampaknya gagal ketika Anda memiliki banyak ekstensi file. Misalnya, pth = Path('data/foo.tar.gz'); print(pth.with_suffix('.jpg'))akan mengeluarkan 'data/foo.tar.jpg'. Saya kira Anda bisa melakukannya pth.with_suffix('').with_suffix('.jpg'), tetapi itu kikuk, dan Anda perlu menambahkan rantai .with_suffix('')panggilan yang panjang secara sewenang-wenang untuk menangani sejumlah titik .dalam ekstensi file (memang, lebih dari 2 adalah kasus tepi eksotis).
telp
@tel Anda dapat menggunakan whileloop untuk menyelesaikannya:pth = Path('data/foo.tar.gz'); while pth != pth.with_suffix(''): pth = pth.with_suffix(''); pth = pth.with_suffix('.jpg')
dericke
Lihat jawaban saya di bawah ini untuk solusi untuk masalah beberapa ekstensi.
Michael Hall
33

Seperti yang dikatakan @jethro, splitextadalah cara terbaik untuk melakukannya. Tetapi dalam kasus ini, cukup mudah untuk membaginya sendiri, karena ekstensi harus menjadi bagian dari nama file yang muncul setelah periode terakhir:

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

Perintah tersebut rsplitmemberitahu Python untuk melakukan pemisahan string mulai dari kanan string, dan perintah 1untuk melakukan paling banyak satu pemisahan (misalnya 'foo.bar.baz'-> [ 'foo.bar', 'baz' ]). Karena rsplitakan selalu mengembalikan array yang tidak kosong, kita dapat mengindeksnya dengan aman 0untuk mendapatkan nama file dikurangi ekstensi.

Katriel
sumber
8
Perhatikan bahwa penggunaan rsplitakan menghasilkan hasil yang berbeda untuk file yang dimulai dengan titik dan tidak memiliki ekstensi lain (seperti file tersembunyi di Linux, misalnya .bashrc). os.path.splitextmengembalikan ekstensi kosong untuk ini, tetapi menggunakan rsplitakan memperlakukan seluruh nama file sebagai ekstensi.
Florian Brucker
4
Ini juga akan memberikan hasil yang tidak terduga untuk nama file/home/john.johnson/somefile
Will Manley
7

Saya lebih suka pendekatan satu baris berikut menggunakan str.rsplit () :

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

Contoh:

>>> my_filename = '/home/user/somefile.txt'
>>> my_filename.rsplit('.', 1)
>>> ['/home/user/somefile', 'txt']
IvanD
sumber
2
Ini gagal jika somefile tidak memiliki ekstensi dan pengguna adalah 'john.doe'.
Marek Jedliński
Bukankah mereka semua akan gagal?
eatmeimadanish
6

Untuk 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'
AnaPana
sumber
1
Saya pikir pendekatan pathlib disarankan oleh JS. jauh lebih sederhana.
h0b0
4

Menangani banyak ekstensi

Dalam kasus di mana Anda memiliki beberapa ekstensi, satu baris ini menggunakan pathlibdan str.replacebekerja dengan baik:

Hapus / strip ekstensi

>>> from pathlib import Path
>>> p = Path("/path/to/myfile.tar.gz")
>>> str(p).replace("".join(p.suffixes), "")
'/path/to/myfile'

Ganti ekstensi

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

Jika Anda juga menginginkan pathlibkeluaran objek maka Anda dapat dengan jelas membungkus barisPath()

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

Membungkus semuanya dalam sebuah fungsi

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')
Michael Hall
sumber
pathlib memiliki pintasan untuk ini: Path (). with_suffix ("") akan menghapus ekstensi dan Path.with_suffix (". txt") akan menggantikannya.
Levi
Benar. Tapi itu hanya menghapus ekstensi pertama. Jadi dalam contoh di atas, menggunakan with_suffixalih-alih replacehanya akan menghapus .gzalih-alih .tar.gz Jawaban saya dimaksudkan untuk menjadi "umum", tetapi jika Anda hanya mengharapkan satu ekstensi, with_suffixakan menjadi solusi yang lebih bersih.
Michael Hall
3

Cara lain yang bisa dilakukan adalah dengan menggunakan str.rpartition(sep)metode tersebut.

Sebagai contoh:

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

new_filename = prefix + '.jpg'

print new_filename
pengguna2802945
sumber