Extraindo a extensão do nome do arquivo em Python


Respostas:


1990

Sim. Use os.path.splitext(consulte a documentação do Python 2.X ou a documentação do Python 3.X ):

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

Ao contrário da maioria das tentativas manuais de divisão de cadeias, os.path.splitexttratará corretamente /a/b.c/dcomo sem extensão em vez de ter extensão .c/d, e tratará .bashrccomo sem extensão em vez de ter extensão .bashrc:

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

15
o uso de basenameé um pouco confuso aqui desde os.path.basename("/path/to/somefile.ext")voltaria"somefile.ext"
Jiaaro

17
não seria endswith()não ser mais portátil e pythônico?
Sebastian Mach

79
@ klingt.net Bem, nesse caso, .asdé realmente a extensão !! Se você pensar bem, foo.tar.gzé um arquivo compactado com gzip ( .gz) que passa a ser um arquivo tar ( .tar). Mas é um arquivo gzip em primeiro lugar. Eu não esperaria que ele retornasse a extensão dupla.
Nosklo

160
A convenção de nomenclatura de funções padrão do Python é realmente irritante - quase todas as vezes que olho para isso, confundo splittext. Se eles fizessem alguma coisa para significar a quebra entre partes desse nome, seria muito mais fácil reconhecer que é splitExtou não split_ext. Certamente não posso ser a única pessoa que cometeu esse erro?
ArtOfWarfare

9
@Vingtoft Você não mencionou nada sobre o FileStorage do werkzeug em seu comentário e esta pergunta não tem nada sobre esse cenário específico. Algo pode estar errado com a forma como você recebe o nome do arquivo. os.path.splitext('somefile.ext')=> ('somefile', '.ext'). Sinta-se à vontade para fornecer um exemplo de contador real sem fazer referência a alguma biblioteca de terceiros.
Gewthen

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

15
Por curiosidade, por que em import os.pathvez de from os import path?
kiswa

2
Ah, eu só estava me perguntando se havia uma razão específica por trás disso (além da convenção). Ainda estou aprendendo Python e queria aprender mais!
kiswa 26/08

55
depende realmente, se você usar from os import path, o nome pathserá usado no seu escopo local, também outros que olham o código podem não saber imediatamente que caminho é o caminho do módulo OS. Onde você usa, import os.pathele o mantém dentro do osnamespace e onde quer que você faça a chamada, as pessoas sabem que é path()do osmódulo imediatamente.
dennmat

18
Sei que não é semanticamente diferente, mas pessoalmente acho a construção _, extension = os.path.splitext(filename)muito mais bonita.
Tim Gilbert

3
Se você deseja a extensão como parte de uma expressão mais complexa, o [1] pode ser mais útil: if check_for_gzip and os.path.splitext(filename)[1] == '.gz':
gerardw 20/02/19

239

Novo na versão 3.4.

import pathlib

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

Estou surpreso que ninguém tenha mencionado pathlibainda, pathlibÉ incrível!

Se você precisar de todos os sufixos (por exemplo, se você tiver um .tar.gz), .suffixesretornará uma lista deles!


12
exemplo para obter .tar.gz:''.join(pathlib.Path('somedir/file.tar.gz').suffixes)
user3780389 3/17/17

Ótima resposta. Achei este tutorial mais útil que a documentação: zetcode.com/python/pathlib
user118967

@ user3780389 Um "foo.bar.tar.gz" ainda não seria um ".tar.gz" válido? Nesse caso, seu snippet deve ser usado .suffixes[-2:]para garantir apenas o máximo de .tar.gz.
jeromej 20/04

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

Para obter apenas o texto da extensão, sem o ponto.


73

Uma opção pode ser dividir do ponto:

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

Não há erro quando o arquivo não tem uma extensão:

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

Mas você deve ter cuidado:

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

4
Este ia ficar chateado se você estiver fazendo o upload x.tar.gz
Kirill

19
Na verdade não. A extensão de um arquivo chamado "x.tar.gz" é "gz" e não "tar.gz". os.path.splitext fornece ".os" como extensão também.
Murat Çorlu

1
podemos usar [1] ao invés de [-1]. Eu não conseguia entender [-1] com split
user765443

7
[-1] para obter o último item dos itens divididos por ponto. Exemplo:"my.file.name.js".split('.') => ['my','file','name','js]
Murat Çorlu 21/08

1
@ BenjaminR ah ok, você está fazendo uma otimização sobre a lista de resultados. ['file', 'tar', 'gz']com 'file.tar.gz'.split('.') vs ['file.tar', 'gz'] com 'file.tar.gz'.rsplit('.', 1). sim, poderia ser.
Murat Çorlu 28/08

40

vale a pena adicionar um mais baixo para que você não se pergunte por que os JPG não estão aparecendo na sua lista.

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

19

Qualquer uma das soluções acima funciona, mas no linux eu descobri que há uma nova linha no final da cadeia de extensão que impedirá que as correspondências tenham êxito. Adicione o strip()método ao final. Por exemplo:

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

1
Para ajudar meu entendimento, você poderia explicar contra qual comportamento adicional o segundo índice / fatia protege? (ou seja, o [1:]in .splittext(filename)[1][1:]) - obrigado antecipadamente
Samuel Harmer 11/11

1
Descobri isso sozinho: splittext()(diferente de se você dividir uma string usando '.') Inclui o '.' caractere na extensão. O adicional [1:]se livra disso.
Samuel Harmer 11/10

17

Com splitext há problemas com arquivos com extensão dupla (por exemplo file.tar.gz, file.tar.bz2, etc ..)

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

mas deve ser: .tar.gz

As soluções possíveis estão aqui


35
Não, ela deve ser .gz
Robert Siemer

1
fazê-lo duas vezes para obter as 2 extensões?
maazza

1
@maazza yep. gunzip somefile.tar.gz qual é o nome do arquivo de saída?
FlipMcF

1
É por isso que temos a extensão 'tgz', que significa: tar + gzip! : D
Nuno Aniceto

1
@ Peterhil Eu não acho que você deseja que seu script python esteja ciente do aplicativo usado para criar o nome do arquivo. Está um pouco fora do escopo da questão. Não escolha o exemplo, 'filename.csv.gz' também é bastante válido.
FlipMcF 15/10

16

Você pode encontrar ótimas coisas no módulo pathlib (disponível no python 3.x).

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

# Output 
'.txt'

14

Embora seja um tópico antigo, mas eu me pergunto por que não há ninguém mencionando uma API muito simples de python chamada rpartition neste caso:

Para obter a extensão de um determinado caminho absoluto do arquivo, basta digitar:

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

exemplo:

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

lhe dará: 'csv'


1
Para aqueles não familiarizados com a API, rpartition retorna uma tupla: ("string before the right-most occurrence of the separator", "the separator itself", "the rest of the string"). Se não houver nenhum separador encontrado, a tupla retornada será: ("", "", "the original string").
Nickolay

13

Apenas jointudo 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

Surpreendeu que isso ainda não tivesse sido mencionado:

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

Benefícios:

  • Funciona como esperado para qualquer coisa que eu possa pensar
  • Sem módulos
  • Sem regex
  • Plataforma cruzada
  • Facilmente extensível (por exemplo, sem pontos iniciais para extensão, apenas a última parte da extensão)

Como função:

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

1
Isso resulta em uma exceção quando o arquivo não tem nenhuma extensão.
thiruvenkadam

4
Esta resposta ignora absolutamente uma variante se um nome de arquivo contiver muitos pontos no nome. Exemplo get_extension ('cmocka-1.1.0.tar.xz') => '.1.0.tar.xz' - errado.
PADYMKO

@PADYMKO, IMHO não deve criar nomes de arquivos com pontos finais como parte do nome do arquivo. O código acima não deve resultar em 'tar.xz'
Douwe van der Leest

2
Apenas mude para [-1]então.
PascalVKooten

11

Você pode usar um splitem um filename:

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

Isso não requer biblioteca adicional


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

2
Isso resulta no último caractere de filenameretorno, se o nome do arquivo não tiver nenhum .. Isso ocorre porque rfindretorna -1se a sequência não for encontrada.
mattst

6

Esta é uma técnica direta de representação de cadeias: vejo muitas soluções mencionadas, mas acho que a maioria está olhando para a divisão. Split, no entanto, faz isso em todas as ocorrências de "." . O que você preferiria procurar é partição.

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

2
rpartition já foi sugerido por @weiyixie .
Nickolay

5

Outra solução com divisão correta:

# 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

Mesmo esta pergunta já foi respondida, eu adicionaria a solução no Regex.

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

1
Ou \.[0-9a-z]+$como neste post .
pault 19/03/18

2

Um verdadeiro one-liner, se você gosta de regex. E isso não importa, mesmo se você tiver "." no meio

import re

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

Veja aqui o resultado: Clique Aqui


0

Este é o método mais simples para obter o nome do arquivo e a extensão em uma única linha .

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

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

Ao contrário de outras soluções, você não precisa importar nenhum pacote para isso.


2
isso não funciona para todos os arquivos ou tipos, por exemplo 'archive.tar.gz
studioj 13/03

0

Para brincadeiras ... basta coletar as extensões em um ditado e acompanhar todas elas em uma pasta. Em seguida, basta puxar as extensões que você deseja.

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)

Essa é uma péssima ideia. Seu código quebra para qualquer extensão de arquivo que você não tenha adicionado anteriormente!
Robert

0

tente isto:

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. obtenha todo o nome do arquivo dentro da lista
  2. dividir o nome do arquivo e verificar a extensão penúltima, está na lista pen_ext ou não?
  3. se sim, junte-o à última extensão e defina-a como extensão do arquivo
  4. se não, basta colocar a última extensão como extensão do arquivo
  5. e então confira

1
Isso ocorre em vários casos especiais. Veja a resposta aceita. Está reinventando o volante, apenas de forma incorreta.
Robert

Eu atualizei minha resposta
Ibnul Husainan 21/04

Olá! Embora esse código possa resolver a questão, incluir uma explicação de como e por que isso resolve o problema realmente ajudaria a melhorar a qualidade da sua postagem e provavelmente resultaria em mais votos positivos. Lembre-se de que você está respondendo à pergunta dos leitores no futuro, não apenas à pessoa que está perguntando agora. Por favor edite sua resposta para adicionar explicações e dar uma indicação do que limitações e premissas se aplicam.
Brian

@ Brian assim?
Ibnul Husainan

Você só está piorando, quebrando de novas maneiras. foo.taré um nome de arquivo válido. O que acontece se eu jogar isso no seu código? Que tal .bashrcou foo? Existe uma função de biblioteca para isso por uma razão ...
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(".")

Isso fornecerá o nome do arquivo até o primeiro ".", Que seria o mais comum.


1
primeiro, ele não precisa do nome, mas de extensão. Segundo, mesmo que ele precisasse de um nome, estaria errado em arquivos como:file.name.ext
ya_dimon 4/11/15

Como mencionado por @ya_dimon, isso não funcionará para nomes de arquivos com pontos. Além disso, ele precisa da extensão!
Umar Dastgir
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.