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', '')
nosklo
fonte
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]
Brian Neal
fonte
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!

jeromej
fonte
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.

wonzbak
fonte
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
Murat Çorlu
fonte
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()
blended
fonte
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() 
yamex5
fonte
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

XavierCLL
fonte
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'
r3t40
fonte
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'

weiyixie
fonte
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'
Alex
fonte
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
PascalVKooten
fonte
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

soheshdoshi
fonte
10
filename='ext.tar.gz'
extension = filename[filename.rfind('.'):]
tempo de permanência
fonte
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]
Kenstars
fonte
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])
Arnaldo P. Figueira Figueira
fonte
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'
Micha
fonte
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

Victor Wang
fonte
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.

Ripon Kumar Saha
fonte
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)
eatmeimadanish
fonte
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
Ibnul Husainan
fonte
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 ""
DragonX
fonte
-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
user5535053
fonte
-5
name_only=file_name[:filename.index(".")

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

wookie
fonte
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