Extracción de extensión del nombre de archivo en Python

Respuestas:

1990

Si. Uso os.path.splitext(consulte la documentación de Python 2.X o la documentación de Python 3.X ):

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

A diferencia de la mayoría de los intentos manuales de división de cadenas, os.path.splitextse tratará correctamente /a/b.c/dcomo sin extensión en lugar de tener extensión .c/d, y se tratará .bashrccomo si no tuviera extensión en lugar de tener extensión .bashrc:

>>> os.path.splitext('/a/b.c/d')
('/a/b.c/d', '')
>>> os.path.splitext('.bashrc')
('.bashrc', '')
nosklo
fuente
15
el uso de basenamees un poco confuso aquí ya os.path.basename("/path/to/somefile.ext")que volvería"somefile.ext"
Jiaaro
17
¿No endswith()sería más portátil y pitónico?
Sebastian Mach
79
@ klingt.net Bueno, en ese caso, ¡ .asdes realmente la extensión! Si lo piensa, foo.tar.gzes un archivo comprimido con gzip ( .gz) que resulta ser un archivo tar ( .tar). Pero es un archivo gzip en primer lugar. No esperaría que devuelva la extensión dual en absoluto.
nosklo
160
La convención de nomenclatura de funciones estándar de Python es realmente molesta: casi cada vez que vuelvo a buscar esto, lo confundo como tal splittext. Si simplemente hicieran algo para significar la ruptura entre partes de este nombre, sería mucho más fácil reconocer que es splitExto split_ext. ¿Seguramente no puedo ser la única persona que ha cometido este error?
ArtOfWarfare
99
@Vingtoft No mencionaste nada sobre FileStorage de werkzeug en tu comentario y esta pregunta no tiene nada sobre ese escenario en particular. Algo podría estar mal con la forma en que se le pasa el nombre de archivo. os.path.splitext('somefile.ext')=> ('somefile', '.ext'). Siéntase libre de proporcionar un ejemplo de contador real sin hacer referencia a alguna biblioteca de terceros.
Gewthen
400
import os.path
extension = os.path.splitext(filename)[1]
Brian Neal
fuente
15
Por curiosidad, ¿por qué en import os.pathlugar de from os import path?
kiswa
2
Oh, me preguntaba si había una razón específica detrás de esto (aparte de la convención). ¡Todavía estoy aprendiendo Python y quería aprender más!
kiswa
55
depende realmente, si lo usa, from os import pathentonces el nombre pathse toma en su ámbito local, también otros que miran el código pueden no saber de inmediato que la ruta es la ruta desde el módulo os. Donde, como si lo usa, import os.pathlo mantiene dentro del osespacio de nombres y donde sea que realice la llamada, la gente sabe que es path()del osmódulo inmediatamente.
dennmat
18
Sé que no es semánticamente diferente, pero personalmente considero que la construcción _, extension = os.path.splitext(filename)es mucho más bonita.
Tim Gilbert
3
Si desea la extensión como parte de una expresión más compleja, el [1] puede ser más útil: if check_for_gzip and os.path.splitext(filename)[1] == '.gz':
gerardw
239

Nuevo en la versión 3.4.

import pathlib

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

Me sorprende que nadie haya mencionado pathlibaún, ¡ pathlibES increíble!

Si necesita todos los sufijos (por ejemplo, si tiene un .tar.gz), ¡ .suffixesle devolverá una lista!

jeromej
fuente
12
ejemplo para obtener .tar.gz:''.join(pathlib.Path('somedir/file.tar.gz').suffixes)
user3780389
Gran respuesta. Este tutorial me pareció más útil que la documentación: zetcode.com/python/pathlib
user118967
@ user3780389 ¿No sería un "foo.bar.tar.gz" todavía válido ".tar.gz"? Si es así, su fragmento debe usarse .suffixes[-2:]para garantizar que solo obtenga .tar.gz como máximo.
jeromej
111
import os.path
extension = os.path.splitext(filename)[1][1:]

Para obtener solo el texto de la extensión, sin el punto.

wonzbak
fuente
73

Una opción puede estar dividiéndose del punto:

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

No hay error cuando el archivo no tiene una extensión:

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

Pero debes tener cuidado:

>>> "png".split(".")[-1]
'png'    # But file doesn't have an extension
Murat Çorlu
fuente
44
Esto se enfadaría si está cargando x.tar.gz
Kirill
19
No realmente. La extensión de un archivo llamado "x.tar.gz" es "gz" y no "tar.gz". os.path.splitext también proporciona ".os" como extensión.
Murat Çorlu
1
podemos usar [1] en lugar de [-1]. No pude entender [-1] con división
user765443
77
[-1] para obtener el último elemento de elementos que se dividió por punto. Ejemplo:"my.file.name.js".split('.') => ['my','file','name','js]
Murat Çorlu
1
@BenjaminR ah ok, estás haciendo una optimización sobre la lista de resultados. ['file', 'tar', 'gz']con 'file.tar.gz'.split('.') vs ['file.tar', 'gz'] con 'file.tar.gz'.rsplit('.', 1). Sí, podría ser.
Murat Çorlu
40

vale la pena agregar un valor más bajo para que no se pregunte por qué los JPG no aparecen en su lista.

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

Cualquiera de las soluciones anteriores funciona, pero en Linux he encontrado que hay una nueva línea al final de la cadena de extensión que evitará que las coincidencias tengan éxito. Agrega el strip()método hasta el final. Por ejemplo:

import os.path
extension = os.path.splitext(filename)[1][1:].strip() 
yamex5
fuente
1
Para ayudar a mi comprensión, ¿podría explicar contra qué comportamiento adicional protege el segundo índice / corte? (es decir, [1:]en .splittext(filename)[1][1:]) - gracias de antemano
Samuel Harmer
1
Lo descubrí por mí mismo: splittext()(a diferencia de si divide una cadena usando '.') Incluye el '.' personaje en la extensión. El adicional [1:]se deshace de él.
Samuel Harmer
17

Con splitext hay problemas con archivos con doble extensión (p file.tar.gz. Ej . file.tar.bz2, Etc.)

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

pero debe ser: .tar.gz

Las posibles soluciones están aquí

XavierCLL
fuente
35
No, debería ser .gz
Robert Siemer
1
¿Lo haces dos veces para obtener las 2 extensiones?
maazza
1
@maazza sí. gunzip somefile.tar.gz ¿Cuál es el nombre de archivo de salida?
FlipMcF
1
Es por eso que tenemos la extensión 'tgz' que significa: tar + gzip! : D
Nuno Aniceto
1
@peterhil No creo que quieras que tu script de Python esté al tanto de la aplicación utilizada para crear el nombre de archivo. Está un poco fuera del alcance de la pregunta. No elija el ejemplo, 'filename.csv.gz' también es bastante válido.
FlipMcF
16

Puede encontrar algunas cosas excelentes en el módulo pathlib (disponible en python 3.x).

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

# Output 
'.txt'
r3t40
fuente
14

Aunque es un tema antiguo, pero me pregunto por qué no se menciona una API muy simple de Python llamada rpartition en este caso:

para obtener la extensión de una ruta absoluta de un archivo dado, simplemente puede escribir:

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

ejemplo:

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

te dará: 'csv'

weiyixie
fuente
1
Para aquellos que no están familiarizados con la API, rpartition devuelve una tupla: ("string before the right-most occurrence of the separator", "the separator itself", "the rest of the string"). Si no hay un separador encontrado, la tupla devuelta será: ("", "", "the original string").
Nickolay
13

Solo jointodos 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
fuente
12

Sorprendido, esto no fue mencionado todavía:

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

Beneficios:

  • Funciona como se espera para cualquier cosa que se me ocurra.
  • Sin módulos
  • Sin expresiones regulares
  • Multiplataforma
  • Fácilmente extensible (por ejemplo, sin puntos iniciales para la extensión, solo la última parte de la extensión)

Como función:

def get_extension(filename):
    basename = os.path.basename(filename)  # os independent
    ext = '.'.join(basename.split('.')[1:])
    return '.' + ext if ext else None
PascalVKooten
fuente
1
Esto da como resultado una excepción cuando el archivo no tiene ninguna extensión.
thiruvenkadam 01 de
44
Esta respuesta ignora absolutamente una variante si un nombre de archivo contiene muchos puntos en el nombre. Ejemplo get_extension ('cmocka-1.1.0.tar.xz') => '.1.0.tar.xz' - incorrecto.
PADYMKO
@PADYMKO, en mi humilde opinión, uno no debe crear nombres de archivo con puntos completos como parte del nombre de archivo. No se supone que el código anterior dé como resultado 'tar.xz'
Douwe van der Leest
2
Solo cambia a [-1]entonces.
PascalVKooten
11

Puede usar un spliten un filename:

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

Esto no requiere una biblioteca adicional

soheshdoshi
fuente
10
filename='ext.tar.gz'
extension = filename[filename.rfind('.'):]
tiempo de permanencia
fuente
2
Esto da como resultado que filenamese devuelva el último carácter si el nombre de archivo no tiene ninguno .. Esto se debe a que rfinddevuelve -1si no se encuentra la cadena.
mattst
6

Esta es una técnica de representación directa de cadenas: veo muchas soluciones mencionadas, pero creo que la mayoría está buscando dividir. Split, sin embargo, lo hace en cada aparición de "." . Lo que preferirías estar buscando es la partición.

string = "folder/to_path/filename.ext"
extension = string.rpartition(".")[-1]
Kenstars
fuente
2
La partición ya fue sugerida por @weiyixie .
Nickolay
5

Otra solución con división correcta:

# 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
fuente
5

Incluso esta pregunta ya está respondida, agregaría la solución en Regex.

>>> import re
>>> file_suffix = ".*(\..*)"
>>> result = re.search(file_suffix, "somefile.ext")
>>> result.group(1)
'.ext'
Micha
fuente
1
O \.[0-9a-z]+$como en este post .
pausa
2

Una verdadera frase, si te gusta la expresión regular. Y no importa incluso si tiene un "." Adicional en el medio

import re

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

Vea aquí el resultado: haga clic aquí

Victor Wang
fuente
0

Este es el método más simple para obtener tanto el nombre de archivo como la extensión en una sola línea .

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

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

A diferencia de otras soluciones, no necesita importar ningún paquete para esto.

Ripon Kumar Saha
fuente
2
esto no funciona para todos los archivos o tipos, por ejemplo 'archive.tar.gz
studioj
0

Para divertirse ... solo reúna las extensiones en un dict y realice un seguimiento de todas ellas en una carpeta. Luego simplemente extraiga las extensiones que desee.

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
fuente
Esa es una idea terrible. ¡Su código se rompe para cualquier extensión de archivo que no haya agregado previamente!
Robert
0

prueba esto:

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. obtener todo el nombre del archivo dentro de la lista
  2. dividiendo el nombre del archivo y verificando la penúltima extensión, ¿está en la lista pen_ext o no?
  3. en caso afirmativo, únala con la última extensión y configúrela como la extensión del archivo
  4. si no es así, simplemente coloque la última extensión como la extensión del archivo
  5. y luego échale un vistazo
Ibnul Husainan
fuente
1
Esto se rompe para un montón de casos especiales. Ver la respuesta aceptada. Se trata de reinventar la rueda, solo con errores.
Robert
actualicé mi respuesta
Ibnul Husainan
¡Hola! Si bien este código puede resolver la pregunta, incluir una explicación de cómo y por qué esto resuelve el problema realmente ayudaría a mejorar la calidad de su publicación, y probablemente resultaría en más votos positivos. Recuerde que está respondiendo la pregunta para los lectores en el futuro, no solo la persona que pregunta ahora. Por favor, editar su respuesta para agregar explicaciones y dar una indicación de lo que se aplican limitaciones y supuestos.
Brian
@Brian así?
Ibnul Husainan
Solo lo estás empeorando, rompiéndolo de nuevas maneras. foo.tares un nombre de archivo válido ¿Qué pasa si le tiro eso a tu código? ¿Qué hay de .bashrco foo? Hay una función de biblioteca para esto por una razón ...
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
fuente
-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
usuario5535053
fuente
-5
name_only=file_name[:filename.index(".")

Eso le dará el nombre del archivo hasta el primer ".", Que sería el más común.

wookie
fuente
1
primero, no necesita el nombre, sino la extensión. En segundo lugar, incluso si necesitara nombre, sería incorrecto por archivos como:file.name.ext
ya_dimon
Como mencionó @ya_dimon, esto no funcionará para nombres de archivos con puntos. Además, ¡necesita la extensión!
Umar Dastgir