Come sostituire (o rimuovere) un'estensione da un nome di file in Python?


112

Esiste una funzione incorporata in Python che sostituisca (o rimuova, qualunque sia) l'estensione di un nome di file (se ne ha uno)?

Esempio:

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

Nel mio esempio: /home/user/somefile.txtdiventerebbe/home/user/somefile.jpg

Non so se sia importante, ma ne ho bisogno per un modulo SCons che sto scrivendo. (Quindi forse c'è qualche funzione specifica di SCons che posso usare?)

Vorrei qualcosa di pulito . .txtOvviamente non è chiaro fare una semplice sostituzione di stringa di tutte le occorrenze all'interno della stringa. (Questo fallirebbe se il mio nome file fosse somefile.txt.txt.txt)



SCons consente di accedere al filebase in una stringa di azione. Puoi pubblicare la tua logica specifica di scons che ha bisogno di questo? È per l'azione, l'emettitore, lo scanner?
bdbaddog

alcune di queste non sembrano più funzionare in quanto path restituisce un PosixPath non una stringa: p
shigeta

Risposte:


146

Prova os.path.splitext dovrebbe fare quello che vuoi.

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

15
@ S.Lott: Credimi o no. Ma l'ho fatto. Lo faccio sempre. Forse con i termini sbagliati.
ereIl

@ereOn: Poiché la tua domanda utilizza quasi la stessa identica frase, sono un po 'sorpreso che tu non l'abbia trovata. La tua domanda ha 5 parole, di seguito, che corrispondono esattamente.
S.Lott

Metti il ​​nuovo nome solo insieme a os.path.join per sembrare pulito.
Tony Veijalainen

4
@Tony Veijalainen: Non dovresti usare os.path.join perché serve per unire i componenti del percorso con il separatore di percorso specifico del sistema operativo. Ad esempio, print os.path.join(os.path.splitext('/home/user/somefile.txt')[0], '.jpg')tornerà /home/user/somefile/.jpg, il che non è desiderabile.
scottclowe

@ S.Lott - 99 persone che votano positivamente questa risposta significa chiaramente che questo post è utile, non c'è bisogno di vergognarsi in maiuscolo
JeffThompson

91

Espandendo la risposta di AnaPana, come rimuovere un'estensione usando 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 ha una buona descrizione di casi d'uso di esempio del modulo pathlib
Steven C. Howell

2
Questa risposta è il mio approccio tipico, ma sembra fallire quando si hanno più estensioni di file. Ad esempio, pth = Path('data/foo.tar.gz'); print(pth.with_suffix('.jpg'))verrà prodotto 'data/foo.tar.jpg'. Suppongo che tu possa farlo pth.with_suffix('').with_suffix('.jpg'), ma è goffo, e dovresti aggiungere una catena di .with_suffix('')chiamate arbitrariamente lunga per gestire un numero arbitrario di punti .in un'estensione di file (ammettiamolo, più di 2 è un caso limite esotico).
tel

@tel Potresti usare un whileciclo per risolverlo:pth = Path('data/foo.tar.gz'); while pth != pth.with_suffix(''): pth = pth.with_suffix(''); pth = pth.with_suffix('.jpg')
dericke

Vedi la mia risposta di seguito per una soluzione al problema delle estensioni multiple.
Michael Hall,

33

Come ha detto @jethro, splitextè il modo migliore per farlo. Ma in questo caso, è abbastanza facile dividerlo da soli, poiché l'estensione deve essere la parte del nome del file che viene dopo il punto finale:

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

Il rsplitdice a Python di eseguire le suddivisioni delle stringhe a partire dalla destra della stringa, e 1dice di eseguire al massimo una divisione (in modo che ad esempio 'foo.bar.baz'-> [ 'foo.bar', 'baz' ]). Poiché rsplitrestituirà sempre un array non vuoto, possiamo indicizzarlo 0in modo sicuro per ottenere il nome del file meno l'estensione.


8
Nota che l'utilizzo rsplitdarà risultati diversi per i file che iniziano con un punto e non hanno altre estensioni (come i file nascosti su Linux, ad esempio .bashrc). os.path.splitextrestituisce un'estensione vuota per questi, ma usando rsplittratterà l'intero nome del file come un'estensione.
Florian Brucker

4
Questo darà anche risultati inaspettati per il nome del file/home/john.johnson/somefile
Will Manley

7

Preferisco il seguente approccio di una riga utilizzando str.rsplit () :

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

Esempio:

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

2
Questo fallisce se il somefile non ha estensione e l'utente è "john.doe".
Marek Jedliński

Allora non avrebbero fallito tutti?
eatmeimadanish

6

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

1
Penso che l'approccio pathlib suggerito da JS. è molto più semplice.
h0b0

4

Gestione di più estensioni

Nel caso in cui si disponga di più estensioni, questo monopezzo utilizza pathlibe str.replacefunziona a meraviglia:

Rimuovere / rimuovere le estensioni

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

Sostituisci le estensioni

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

Se vuoi anche un pathliboutput dell'oggetto, puoi ovviamente racchiudere la rigaPath()

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

Racchiudere tutto in una funzione

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 ha una scorciatoia per questo: Path (). with_suffix ("") rimuoverà un'estensione e Path.with_suffix (". txt") la sostituirà.
Levi

Corretta. Ma rimuove solo la prima estensione. Quindi, nell'esempio sopra, usare with_suffixinvece di replacerimuoverà solo .gzinvece di La .tar.gz mia risposta era intesa come "generale", ma se ti aspettassi solo una singola estensione, with_suffixsarebbe una soluzione più pulita.
Michael Hall,

3

Un altro modo per farlo è utilizzare il str.rpartition(sep)metodo.

Per esempio:

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

new_filename = prefix + '.jpg'

print new_filename
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.