Estrazione dell'estensione dal nome file in Python


Risposte:


1990

Sì. Utilizzare os.path.splitext(consultare la documentazione di Python 2.X o la documentazione di Python 3.X ):

>>> import os
>>> filename, file_extension = os.path.splitext('/path/to/somefile.ext')
>>> filename
'/path/to/somefile'
>>> file_extension
'.ext'

A differenza della maggior parte dei tentativi di suddivisione manuale delle stringhe, os.path.splitexttratterà correttamente /a/b.c/dcome non avere estensione invece di avere estensione .c/de tratterà .bashrccome non avere estensione invece di avere estensione .bashrc:

>>> os.path.splitext('/a/b.c/d')
('/a/b.c/d', '')
>>> os.path.splitext('.bashrc')
('.bashrc', '')

15
l'uso di basenameè un po 'confuso da quando os.path.basename("/path/to/somefile.ext")sarebbe tornato"somefile.ext"
Jiaaro

17
Non sarebbe endswith()non essere più portatile e divinatorio?
Sebastian Mach,

79
@ klingt.net Bene, in quel caso, .asdè davvero l'estensione !! Se ci pensate, foo.tar.gzè un file compresso con gzip ( .gz) che sembra essere un file tar ( .tar). Ma è un file gzip al primo posto. Non mi aspetto che restituisca affatto la doppia estensione.
nosklo,

160
La convenzione standard di denominazione delle funzioni Python è davvero fastidiosa - quasi ogni volta che riesco a cercarlo, lo confondo come tale splittext. Se farebbero qualsiasi cosa per indicare l'interruzione tra parti di questo nome, sarebbe molto più facile riconoscere che è splitExto split_ext. Sicuramente non posso essere l'unica persona che ha fatto questo errore?
ArtOfWarfare il

9
@Vingtoft Nel tuo commento non hai menzionato nulla del FileStorage di werkzeug e questa domanda non ha nulla su quel particolare scenario. Potrebbe esserci qualcosa di sbagliato nel modo in cui ti è stato passato il nome file. os.path.splitext('somefile.ext')=> ('somefile', '.ext'). Sentiti libero di fornire un esempio di contatore reale senza fare riferimento a una libreria di terze parti.
Gewthen,

400
import os.path
extension = os.path.splitext(filename)[1]

15
Per curiosità, perché import os.pathinvece di from os import path?
kiswa,

2
Oh, mi stavo solo chiedendo se ci fosse un motivo specifico dietro (diverso dalla convenzione). Sto ancora imparando Python e volevo saperne di più!
kiswa,

55
dipende davvero, se lo usi from os import pathallora il nome pathviene preso nel tuo ambito locale, anche altri che guardano il codice potrebbero non sapere immediatamente che path è il percorso dal modulo os. Dove se lo usi, import os.pathlo mantiene nello osspazio dei nomi e ovunque tu faccia la chiamata, le persone sanno che path()proviene osimmediatamente dal modulo.
Dennmat,

18
So che non è semanticamente diverso, ma personalmente trovo che la costruzione _, extension = os.path.splitext(filename)sia molto più bella.
Tim Gilbert,

3
Se si desidera l'estensione come parte di un'espressione più complessa, [1] potrebbe essere più utile: if check_for_gzip and os.path.splitext(filename)[1] == '.gz':
gerardw,

239

Novità nella versione 3.4.

import pathlib

print(pathlib.Path('yourPath.example').suffix) # '.example'

Sono sorpreso che nessuno abbia pathlibancora menzionato , pathlibÈ fantastico!

Se hai bisogno di tutti i suffissi (ad esempio se hai un .tar.gz), .suffixesverrà restituito un elenco di essi!


12
esempio per ottenere .tar.gz:''.join(pathlib.Path('somedir/file.tar.gz').suffixes)
user3780389

Bella risposta. Ho trovato questo tutorial più utile della documentazione: zetcode.com/python/pathlib
user118967

@ user3780389 Un "foo.bar.tar.gz" non sarebbe comunque valido ".tar.gz"? In tal caso, lo snippet dovrebbe essere utilizzato .suffixes[-2:]per assicurarsi di ottenere solo .tar.gz al massimo.
Jeromej,

111
import os.path
extension = os.path.splitext(filename)[1][1:]

Per ottenere solo il testo dell'estensione, senza il punto.


73

Un'opzione potrebbe essere la divisione dal punto:

>>> filename = "example.jpeg"
>>> filename.split(".")[-1]
'jpeg'

Nessun errore quando il file non ha estensione:

>>> "filename".split(".")[-1]
'filename'

Ma devi stare attento:

>>> "png".split(".")[-1]
'png'    # But file doesn't have an extension

4
Questo sarebbe sconvolgente se stai caricando x.tar.gz
Kirill

19
Non attualmente. L'estensione di un file chiamato "x.tar.gz" è "gz" non "tar.gz". os.path.splitext fornisce anche ".os" come estensione.
Murat Çorlu,

1
possiamo usare [1] anziché [-1]. Non riuscivo a capire [-1] con split
user765443

7
[-1] per ottenere l'ultimo elemento di elementi diviso per punto. Esempio:"my.file.name.js".split('.') => ['my','file','name','js]
Murat Çorlu

1
@BenjaminR ah ok, stai ottimizzando la lista dei risultati. ['file', 'tar', 'gz']con 'file.tar.gz'.split('.') vs ['file.tar', 'gz'] con 'file.tar.gz'.rsplit('.', 1). sì, potrebbe essere.
Murat Çorlu,

40

vale la pena aggiungere un valore inferiore in modo da non chiederti perché i JPG non vengono visualizzati nell'elenco.

os.path.splitext(filename)[1][1:].strip().lower()

19

Tutte le soluzioni sopra funzionano, ma su Linux ho scoperto che c'è una nuova riga alla fine della stringa di estensione che impedirà il successo delle partite. Aggiungi il strip()metodo alla fine. Per esempio:

import os.path
extension = os.path.splitext(filename)[1][1:].strip() 

1
Per facilitare la mia comprensione, potresti spiegare quale comportamento aggiuntivo il secondo indice / slice protegge? (vale [1:]a dire l' in .splittext(filename)[1][1:]) - grazie in anticipo
Samuel Harmer,

1
Ho capito da solo: splittext()(a differenza di quando dividi una stringa usando '.') Include '.' carattere nell'estensione. L'ulteriore [1:]si sbarazza di esso.
Samuel Harmer,

17

Con splitext ci sono problemi con i file con doppia estensione (ad es. file.tar.gz, Ecc file.tar.bz2.)

>>> fileName, fileExtension = os.path.splitext('/path/to/somefile.tar.gz')
>>> fileExtension 
'.gz'

ma dovrebbe essere: .tar.gz

Le possibili soluzioni sono qui


35
No, dovrebbe essere .gz
Robert Siemer,

1
farlo due volte per ottenere le 2 estensioni?
Maazza,

1
@maazza yep. gunzip somefile.tar.gz qual è il nome del file di output?
FlipMcF,

1
Questo è il motivo per cui abbiamo l'estensione 'tgz' che significa: tar + gzip! : D
Nuno Aniceto,

1
@peterhil Non penso che tu voglia che il tuo script Python sia a conoscenza dell'applicazione utilizzata per creare il nome file. È un po 'fuori dalla portata della domanda. Non prendere l'esempio, 'nomefile.csv.gz' è anche abbastanza valido.
FlipMcF,

16

Puoi trovare alcune cose fantastiche nel modulo pathlib (disponibile in Python 3.x).

import pathlib
x = pathlib.PurePosixPath("C:\\Path\\To\\File\\myfile.txt").suffix
print(x)

# Output 
'.txt'

14

Anche se è un vecchio argomento, ma mi chiedo perché non ci sia nessuno che menzioni un api di python molto semplice chiamato partizione in questo caso:

per ottenere l'estensione di un determinato percorso assoluto del file, puoi semplicemente digitare:

filepath.rpartition('.')[-1]

esempio:

path = '/home/jersey/remote/data/test.csv'
print path.rpartition('.')[-1]

ti darà: 'csv'


1
Per chi non ha familiarità con l'API, rpartition restituisce una tupla: ("string before the right-most occurrence of the separator", "the separator itself", "the rest of the string"). Se non c'è separazione trovato, la tupla restituita sarà: ("", "", "the original string").
Nickolay,

13

Proprio jointutto pathlib suffixes.

>>> x = 'file/path/archive.tar.gz'
>>> y = 'file/path/text.txt'
>>> ''.join(pathlib.Path(x).suffixes)
'.tar.gz'
>>> ''.join(pathlib.Path(y).suffixes)
'.txt'

12

Sorpreso, questo non è stato ancora menzionato:

import os
fn = '/some/path/a.tar.gz'

basename = os.path.basename(fn)  # os independent
Out[] a.tar.gz

base = basename.split('.')[0]
Out[] a

ext = '.'.join(basename.split('.')[1:])   # <-- main part

# if you want a leading '.', and if no result `None`:
ext = '.' + ext if ext else None
Out[] .tar.gz

Benefici:

  • Funziona come previsto per qualsiasi cosa mi venga in mente
  • Nessun modulo
  • Nessuna regex
  • Cross-platform
  • Facilmente estensibile (ad es. Nessun punto iniziale per l'estensione, solo l'ultima parte dell'estensione)

Come funzione:

def get_extension(filename):
    basename = os.path.basename(filename)  # os independent
    ext = '.'.join(basename.split('.')[1:])
    return '.' + ext if ext else None

1
Ciò si traduce in un'eccezione quando il file non ha alcuna estensione.
thiruvenkadam,

4
Questa risposta ignora assolutamente una variante se un nome file contiene molti punti nel nome. Esempio get_extension ('cmocka-1.1.0.tar.xz') => '.1.0.tar.xz' - errato.
PADYMKO,

@PADYMKO, IMHO non si dovrebbero creare nomi di file con battute complete come parte del nome del file. Il codice sopra riportato non dovrebbe comportare "tar.xz"
Douwe van der Leest,

2
Basta passare a [-1]allora.
PascalVKooten,

11

Puoi usare a splitsu a filename:

f_extns = filename.split(".")
print ("The extension of the file is : " + repr(f_extns[-1]))

Questo non richiede libreria aggiuntiva


10
filename='ext.tar.gz'
extension = filename[filename.rfind('.'):]

2
Ciò comporta la filenamerestituzione dell'ultimo carattere se il nome file non ha .affatto. Questo perché rfindritorna -1se la stringa non viene trovata.
mattst

6

Questa è una tecnica di rappresentazione diretta delle stringhe: vedo molte soluzioni menzionate, ma penso che la maggior parte stia guardando la divisione. Split lo fa comunque ad ogni occorrenza di "." . Quello che preferiresti cercare è la partizione.

string = "folder/to_path/filename.ext"
extension = string.rpartition(".")[-1]

2
la partizione era già stata suggerita da @weiyixie .
Nickolay,

5

Un'altra soluzione con la giusta divisione:

# to get extension only

s = 'test.ext'

if '.' in s: ext = s.rsplit('.', 1)[1]

# or, to get file name and extension

def split_filepath(s):
    """
    get filename and extension from filepath 
    filepath -> (filename, extension)
    """
    if not '.' in s: return (s, '')
    r = s.rsplit('.', 1)
    return (r[0], r[1])

5

Anche a questa domanda è già stata data risposta Aggiungerei la soluzione in Regex.

>>> import re
>>> file_suffix = ".*(\..*)"
>>> result = re.search(file_suffix, "somefile.ext")
>>> result.group(1)
'.ext'

1
O \.[0-9a-z]+$come in questo post .
pault

2

Un vero one-liner, se ti piace regex. E non importa anche se hai "". nel mezzo

import re

file_ext = re.search(r"\.([^.]+)$", filename).group(1)

Vedi qui per il risultato: clicca qui


0

Questo è il metodo più semplice per ottenere sia il nome file che l'estensione in una sola riga .

fName, ext = 'C:/folder name/Flower.jpeg'.split('/')[-1].split('.')

>>> print(fName)
Flower
>>> print(ext)
jpeg

A differenza di altre soluzioni, non è necessario importare alcun pacchetto per questo.


2
questo non funziona per tutti i file o tipi, ad esempio 'archive.tar.gz
studioj

0

Per i più divertenti ... basta raccogliere le estensioni in un dict e tracciarle tutte in una cartella. Quindi basta estrarre le estensioni desiderate.

import os

search = {}

for f in os.listdir(os.getcwd()):
    fn, fe = os.path.splitext(f)
    try:
        search[fe].append(f)
    except:
        search[fe]=[f,]

extensions = ('.png','.jpg')
for ex in extensions:
    found = search.get(ex,'')
    if found:
        print(found)

È un'idea terribile. Il codice si interrompe per qualsiasi estensione di file che non hai aggiunto in precedenza!
Robert,

0

prova questo:

files = ['file.jpeg','file.tar.gz','file.png','file.foo.bar','file.etc']
pen_ext = ['foo', 'tar', 'bar', 'etc']

for file in files: #1
    if (file.split(".")[-2] in pen_ext): #2
        ext =  file.split(".")[-2]+"."+file.split(".")[-1]#3
    else:
        ext = file.split(".")[-1] #4
    print (ext) #5
  1. ottenere tutto il nome del file all'interno dell'elenco
  2. dividere il nome del file e controllare la penultima estensione, è nell'elenco pen_ext o no?
  3. se sì, uniscilo con l'ultima estensione e impostalo come estensione del file
  4. in caso contrario, basta inserire l'ultima estensione come estensione del file
  5. e poi dai un'occhiata

1
Questo si interrompe per un sacco di casi speciali. Vedi la risposta accettata Sta reinventando la ruota, solo in modo errato.
Robert,

ho aggiornato la mia risposta
Ibnul Husainan il

Ciao! Sebbene questo codice possa risolvere la domanda, inclusa una spiegazione di come e perché questo risolva il problema, contribuirebbe davvero a migliorare la qualità del tuo post e probabilmente darebbe più voti positivi. Ricorda che stai rispondendo alla domanda per i lettori in futuro, non solo per la persona che chiede ora. Si prega di modificare la risposta per aggiungere spiegazioni e dare un'indicazione di ciò si applicano le limitazioni e le assunzioni.
Brian,

@Brian così?
Ibnul Husainan,

Stai solo peggiorando le cose, spezzandolo in nuovi modi. foo.tarè un nome file valido. Cosa succede se lo lancio al tuo codice? Che dire di .bashrco foo? C'è una funzione di libreria per questo per un motivo ...
Robert,

-2
# try this, it works for anything, any length of extension
# e.g www.google.com/downloads/file1.gz.rs -> .gz.rs

import os.path

class LinkChecker:

    @staticmethod
    def get_link_extension(link: str)->str:
        if link is None or link == "":
            return ""
        else:
            paths = os.path.splitext(link)
            ext = paths[1]
            new_link = paths[0]
            if ext != "":
                return LinkChecker.get_link_extension(new_link) + ext
            else:
                return ""

-3
def NewFileName(fichier):
    cpt = 0
    fic , *ext =  fichier.split('.')
    ext = '.'.join(ext)
    while os.path.isfile(fichier):
        cpt += 1
        fichier = '{0}-({1}).{2}'.format(fic, cpt, ext)
    return fichier

-5
name_only=file_name[:filename.index(".")

Questo ti darà il nome del file fino al primo ".", Che sarebbe il più comune.


1
in primo luogo, non ha bisogno del nome, ma dell'estensione. Secondo, anche se avesse bisogno di un nome, sarebbe sbagliato con file come:file.name.ext
ya_dimon

Come menzionato da @ya_dimon, questo non funzionerà per i nomi di file con punti. Inoltre, ha bisogno dell'estensione!
Umar Dastgir,
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.