Python'da bir dosya adından bir uzantı nasıl değiştirilir (veya çıkarılır)?


114

Python'da bir dosya adının uzantısını (varsa) değiştirecek (veya kaldıracak yerleşik bir işlev var mı?

Misal:

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

Örneğimde: /home/user/somefile.txtolur/home/user/somefile.jpg

Önemli mi bilmiyorum ama yazdığım bir SCons modülü için buna ihtiyacım var. (Öyleyse belki kullanabileceğim SCons'a özgü bazı işlevler vardır?)

Temiz bir şey istiyorum . Dize içindeki tüm oluşumların basit bir dizge değişimini yapmak .txtaçıkça temiz değildir. (Dosya adım ise bu başarısız olur somefile.txt.txt.txt)



SCons, bir eylem dizesinde dosya tabanına ulaşmaya izin verir. Scons'a buna ihtiyaç duyan belirli mantığı gönderebilir misin? Bu aksiyon için mi, yayıcı mı, tarayıcı mı?
bdbaddog

yol bir dizge değil PosixPath döndürdüğü için bunların bir kısmı artık işe yaramıyor gibi görünüyor: p
shigeta

Yanıtlar:


147

Os.path.splitext'i deneyin, istediğinizi yapmalıdır.

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

15
@ S.Lott: Bana inanın ya da inanmayın. Ama yaptım. Her zaman yaparım. Belki yanlış şartlarla.
ereOn

@ereOn: Sorunuz hemen hemen aynı ifadeyi kullandığından, bulmamanıza biraz şaşırdım. Sorunuzda tam olarak eşleşen 5 kelime - arka arkaya - var.
S.Lott

Temiz görünmek için yeni adı sadece os.path.join ile birleştirin.
Tony Veijalainen

4
@Tony Veijalainen: os.path.join'i kullanmamalısınız çünkü bu, yol bileşenlerini işletim sistemine özgü yol ayırıcıyla birleştirmek içindir. Örneğin, arzu edilmeyen bir print os.path.join(os.path.splitext('/home/user/somefile.txt')[0], '.jpg')şekilde geri dönecektir /home/user/somefile/.jpg.
scottclowe

@ S.Lott - 99 kişinin bu cevaba oy vermesi oldukça açık bir şekilde bu gönderinin faydalı olduğu anlamına geliyor, büyük harflerle utandırmaya gerek yok
JeffThompson

92

AnaPana cevabı üzerine genişletilmesi, nasıl kaldırmak bir uzantısı kullanarak 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

1
Real Python, pathlib modülünün örnek kullanım durumlarının iyi bir yazımına sahiptir: realpython.com/python-pathlib
Steven C. Howell

2
Bu cevap benim tipik yaklaşımım, ancak birden fazla dosya uzantınız olduğunda başarısız oluyor gibi görünüyor. Örneğin pth = Path('data/foo.tar.gz'); print(pth.with_suffix('.jpg'))çıktı alacaktır 'data/foo.tar.jpg'. Sanırım yapabilirsin pth.with_suffix('').with_suffix('.jpg'), ama bu hantal ve bir dosya uzantısında .with_suffix('')rastgele sayıda noktayla başa çıkmak için rastgele uzun bir çağrı zinciri eklemeniz gerekir .(kuşkusuz, 2'den fazlası egzotik bir uç durumdur).
tel

@tel Bunu whileçözmek için bir döngü kullanabilirsiniz :pth = Path('data/foo.tar.gz'); while pth != pth.with_suffix(''): pth = pth.with_suffix(''); pth = pth.with_suffix('.jpg')
dericke

Bkz aşağıda Cevabımı birden uzantıları soruna bir çözüm.
Michael Hall

33

@ Jethro'nun dediği gibi, splitextbunu yapmanın en iyi yolu. Ancak bu durumda, uzantı dosya adının son periyottan sonra gelen parçası olması gerektiğinden , onu kendiniz bölmek oldukça kolaydır :

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

rsplitDize sağdan başlayarak dize böler gerçekleştirmek için Python söyler ve 1en fazla bir bölme de gerçekleştirmek için diyor (böylece örneğin 'foo.bar.baz'-> [ 'foo.bar', 'baz' ]). Yana rsplithep boş olmayan bir dizi döndürür, biz endeksi güvenle may 0dosya adı eksi uzantısını almak için içine.


8
Kullanmanın rsplit, nokta ile başlayan ve başka uzantısı olmayan dosyalar için farklı sonuçlara yol açacağını unutmayın (Linux'taki gizli dosyalar gibi .bashrc). os.path.splitextbunlar için boş bir uzantı döndürür, ancak kullanılması rsplittüm dosya adını bir uzantı olarak değerlendirir.
Florian Brucker

4
Bu aynı zamanda dosya adı için beklenmeyen sonuçlar verecektir/home/john.johnson/somefile
Will Manley

7

Str.rsplit () kullanarak aşağıdaki tek satırlık yaklaşımı tercih ediyorum :

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

Misal:

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

2
Dosya uzantısı yoksa ve kullanıcı 'john.doe' ise bu başarısız olur.
Marek Jedliński

O halde hepsi başarısız olmaz mı?
eatmeimadanish

6

Python> = 3.4 için:

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'

1
JS tarafından önerilen pathlib yaklaşımını düşünüyorum. çok daha basit.
h0b0

4

Birden çok uzantıyı kullanma

Birden fazla uzantıya sahipseniz, bu tek satırlık pathlibvestr.replace bir tedavi çalışıyor:

Uzantıları kaldır / çıkar

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

Uzantıları değiştirin

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

Ayrıca bir pathlibnesne çıktısı istiyorsanız, satırı açıkça kaydırabilirsiniz.Path()

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

Hepsini bir fonksiyona sarmak

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')

pathlib'in bunun için bir kısayolu vardır: Path (). with_suffix ("") bir uzantıyı kaldıracak ve Path.with_suffix (". txt") onun yerini alacaktır.
Levi

Doğru. Ancak yalnızca ilk uzantıyı kaldırır. Yani yukarıdaki örnekte kullanarak with_suffixyerine replacesadece çıkarıyoruz .gzyerine .tar.gz Benim cevabım "genel" olarak düşünülmüştü, ancak yalnızca tek bir uzantısı bekliyorsanız, with_suffixdaha temiz bir çözüm olacaktır.
Michael Hall

3

Yapmanın başka bir yolu da str.rpartition(sep)yöntemi kullanmaktır .

Örneğin:

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

new_filename = prefix + '.jpg'

print new_filename
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.