Ekstrak ekstensi dari nama file dengan Python

Jawaban:

1990

Iya. Gunakan os.path.splitext(lihat dokumentasi Python 2.X atau dokumentasi Python 3.X ):

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

Tidak seperti kebanyakan upaya pemisahan string manual, os.path.splitextakan memperlakukan dengan benar /a/b.c/dsebagai tidak memiliki ekstensi alih-alih memiliki ekstensi .c/d, dan itu akan diperlakukan .bashrcsebagai tidak memiliki ekstensi alih-alih memiliki ekstensi .bashrc:

>>> os.path.splitext('/a/b.c/d')
('/a/b.c/d', '')
>>> os.path.splitext('.bashrc')
('.bashrc', '')
nosklo
sumber
15
penggunaan basenamesedikit membingungkan di sini karena os.path.basename("/path/to/somefile.ext")akan kembali"somefile.ext"
Jiaaro
17
tidak akan endswith()tidak lebih portabel dan pythonic?
Sebastian Mach
79
@ klingt.net Nah, kalau begitu, .asdini benar-benar ekstensi !! Jika Anda memikirkannya, foo.tar.gzadalah file terkompresi gzip ( .gz) yang merupakan file tar ( .tar). Tapi itu adalah file gzip di tempat pertama. Saya tidak berharap untuk mengembalikan ekstensi ganda sama sekali.
nosklo
160
Konvensi penamaan fungsi Python standar benar-benar menjengkelkan - hampir setiap kali saya melihat kembali ini, saya salah mengartikannya splittext. Jika mereka hanya melakukan apa saja untuk menandakan jeda antara bagian dari nama ini, akan lebih mudah untuk mengenali bahwa itu adalah splitExtatau split_ext. Tentunya saya bukan satu-satunya orang yang melakukan kesalahan ini?
ArtOfWarfare
9
@Vingtoft Anda tidak menyebut-nyebut tentang FileStorage werkzeug dalam komentar Anda dan pertanyaan ini tidak ada hubungannya dengan skenario tertentu. Mungkin ada yang salah dengan cara Anda memasukkan nama file. os.path.splitext('somefile.ext')=> ('somefile', '.ext'). Jangan ragu memberikan contoh penghitung yang sebenarnya tanpa merujuk beberapa perpustakaan pihak ketiga.
Gewthen
400
import os.path
extension = os.path.splitext(filename)[1]
Brian Neal
sumber
15
Karena penasaran, mengapa import os.pathbukan from os import path?
Kiswa
2
Oh, saya hanya ingin tahu apakah ada alasan khusus di baliknya (selain dari konvensi). Saya masih belajar Python dan ingin belajar lebih banyak!
Kiswa
55
itu benar-benar tergantung, jika Anda menggunakan from os import pathmaka nama pathdiambil di lingkup lokal Anda, juga orang lain yang melihat kode mungkin tidak segera tahu bahwa path adalah path dari modul os. Di mana seolah-olah Anda menggunakannya import os.pathmenyimpannya dalam osnamespace dan di mana pun Anda membuat panggilan, orang tahu itu path()dari osmodul segera.
dennmat
18
Saya tahu ini tidak berbeda secara semantik, tetapi saya pribadi menganggap konstruksinya _, extension = os.path.splitext(filename)jauh lebih bagus.
Tim Gilbert
3
Jika Anda ingin ekstensi sebagai bagian dari ekspresi yang lebih kompleks, [1] mungkin lebih berguna: if check_for_gzip and os.path.splitext(filename)[1] == '.gz':
gerardw
239

Baru dalam versi 3.4.

import pathlib

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

Saya terkejut belum ada yang menyebutkan pathlib, pathlibLUAR BIASA!

Jika Anda membutuhkan semua sufiks (mis. Jika Anda memiliki .tar.gz), .suffixesakan mengembalikan daftar sufiks !

jeromej
sumber
12
contoh untuk mendapatkan .tar.gz:''.join(pathlib.Path('somedir/file.tar.gz').suffixes)
user3780389
Jawaban yang bagus Saya menemukan tutorial ini lebih berguna daripada dokumentasi: zetcode.com/python/pathlib
user118967
@ user3780389 Bukankah "foo.bar.tar.gz" masih valid ".tar.gz"? Jika demikian, cuplikan Anda harus digunakan .suffixes[-2:]untuk memastikan hanya mendapatkan .tar.gz paling banyak.
jeromej
111
import os.path
extension = os.path.splitext(filename)[1][1:]

Untuk hanya mendapatkan teks ekstensi, tanpa titik.

wonzbak
sumber
73

Satu opsi mungkin terpisah dari titik:

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

Tidak ada kesalahan saat file tidak memiliki ekstensi:

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

Tetapi Anda harus berhati-hati:

>>> "png".split(".")[-1]
'png'    # But file doesn't have an extension
Murat Çorlu
sumber
4
Ini akan menjadi kesal jika Anda mengunggah x.tar.gz
Kirill
19
Sebenarnya tidak. Perpanjangan file bernama "x.tar.gz" adalah "gz" bukan "tar.gz". os.path.splitext memberikan ".os" sebagai ekstensi juga.
Murat Çorlu
1
bisakah kita menggunakan [1] daripada [-1]. Saya tidak bisa mengerti [-1] dengan split
user765443
7
[-1] untuk mendapatkan item terakhir dari item yang dipisahkan oleh titik. Contoh:"my.file.name.js".split('.') => ['my','file','name','js]
Murat Çorlu
1
@BenjaminR ah ok, Anda membuat optimasi tentang daftar hasil. ['file', 'tar', 'gz']dengan 'file.tar.gz'.split('.') vs ['file.tar', 'gz'] dengan 'file.tar.gz'.rsplit('.', 1). ya, bisa jadi.
Murat Çorlu
40

layak ditambahkan yang lebih rendah di sana sehingga Anda tidak bertanya-tanya mengapa JPG tidak muncul dalam daftar Anda.

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

Salah satu solusi di atas berfungsi, tetapi di linux saya telah menemukan bahwa ada baris baru di akhir string ekstensi yang akan mencegah kecocokan dari berhasil. Tambahkan strip()metode sampai akhir. Sebagai contoh:

import os.path
extension = os.path.splitext(filename)[1][1:].strip() 
yamex5
sumber
1
Untuk membantu pemahaman saya, bisakah Anda menjelaskan perilaku tambahan apa yang dijaga oleh indeks / slice kedua? (ie the [1:]in .splittext(filename)[1][1:]) - terima kasih sebelumnya
Samuel Harmer
1
Mencari tahu sendiri: splittext()(tidak seperti jika Anda memisahkan string menggunakan '.') Termasuk '.' karakter dalam ekstensi. Tambahan [1:]menghilangkannya.
Samuel Harmer
17

Dengan splitext ada masalah dengan file dengan ekstensi ganda (mis file.tar.gz. file.tar.bz2, Dll.)

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

tetapi harus: .tar.gz

Solusi yang mungkin ada di sini

XavierCLL
sumber
35
Tidak, seharusnya .gz
Robert Siemer
1
lakukan dua kali untuk mendapatkan 2 ekstensi?
maazza
1
@maazza ya. gunzip somefile.tar.gz apa nama file keluaran?
FlipMcF
1
Inilah sebabnya kami memiliki ekstensi 'tgz' yang artinya: tar + gzip! : D
Nuno Aniceto
1
@ Peterhil Saya tidak berpikir Anda ingin skrip python Anda untuk mengetahui aplikasi yang digunakan untuk membuat nama file. Itu sedikit keluar dari ruang lingkup pertanyaan. Jangan memilih pada contoh, 'filename.csv.gz' juga cukup valid.
FlipMcF
16

Anda dapat menemukan beberapa hal hebat dalam modul pathlib (tersedia dalam python 3.x).

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

# Output 
'.txt'
r3t40
sumber
14

Meskipun ini adalah topik lama, tetapi saya bertanya-tanya mengapa tidak ada yang menyebutkan api sangat sederhana dari python yang disebut rpartition dalam kasus ini:

untuk mendapatkan ekstensi path absolut file yang diberikan, Anda cukup mengetik:

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

contoh:

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

akan memberi Anda: 'csv'

weiyixie
sumber
1
Bagi yang belum terbiasa dengan API, rpartition mengembalikan tupel: ("string before the right-most occurrence of the separator", "the separator itself", "the rest of the string"). Jika tidak ada pemisah ditemukan, tupel kembali akan: ("", "", "the original string").
Nickolay
13

Hanya joinsemua 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
sumber
12

Terkejut ini belum disebutkan:

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

Manfaat:

  • Bekerja seperti yang diharapkan untuk apa pun yang dapat saya pikirkan
  • Tidak ada modul
  • Tidak ada regex
  • Lintas-platform
  • Mudah diperpanjang (mis. Tidak ada titik utama untuk ekstensi, hanya bagian terakhir dari ekstensi)

Sebagai fungsi:

def get_extension(filename):
    basename = os.path.basename(filename)  # os independent
    ext = '.'.join(basename.split('.')[1:])
    return '.' + ext if ext else None
PascalVKooten
sumber
1
Ini menghasilkan pengecualian ketika file tidak memiliki ekstensi apa pun.
thiruvenkadam
4
Jawaban ini benar-benar mengabaikan varian jika nama file mengandung banyak poin dalam nama. Contoh get_extension ('cmocka-1.1.0.tar.xz') => '.1.0.tar.xz' - salah.
PADYMKO
@ PADYMKO, IMHO kita tidak harus membuat nama file dengan berhenti penuh sebagai bagian dari nama file. Kode di atas tidak seharusnya menghasilkan 'tar.xz'
Douwe van der Leest
2
Ubah saja [-1]saat itu.
PascalVKooten
11

Anda dapat menggunakan splitpada filename:

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

Ini tidak memerlukan perpustakaan tambahan

soheshdoshi
sumber
10
filename='ext.tar.gz'
extension = filename[filename.rfind('.'):]
waktu menginap
sumber
2
Ini menghasilkan karakter terakhir filenameyang dikembalikan jika nama file tidak ada .sama sekali. Ini karena rfindpengembalian -1jika string tidak ditemukan.
mattst
6

Ini adalah teknik representasi string langsung: Saya melihat banyak solusi yang disebutkan, tetapi saya pikir sebagian besar melihat split. Namun Split melakukannya di setiap kemunculan "." . Apa yang Anda lebih suka cari adalah partisi.

string = "folder/to_path/filename.ext"
extension = string.rpartition(".")[-1]
Kenstars
sumber
2
rpartition sudah disarankan oleh @weiyixie .
Nickolay
5

Solusi lain dengan split kanan:

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

Bahkan pertanyaan ini sudah dijawab Saya akan menambahkan solusinya di Regex.

>>> import re
>>> file_suffix = ".*(\..*)"
>>> result = re.search(file_suffix, "somefile.ext")
>>> result.group(1)
'.ext'
Micha
sumber
1
Atau \.[0-9a-z]+$seperti pada postingan ini .
pault
2

Satu-liner sejati, jika Anda suka regex. Dan tidak masalah bahkan jika Anda memiliki tambahan "." di tengah-tengah

import re

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

Lihat di sini untuk hasilnya: Klik Di Sini

Victor Wang
sumber
0

Ini adalah Metode Sederhana untuk mendapatkan Nama File & Ekstensi hanya dalam satu baris .

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

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

Tidak seperti solusi lain, Anda tidak perlu mengimpor paket apa pun untuk ini.

Ripon Kumar Saha
sumber
2
ini tidak bekerja untuk semua file atau tipe misalnya 'archive.tar.gz
studioj
0

Untuk funsies ... kumpulkan saja ekstensi dalam dict, dan lacak semuanya dalam folder. Kemudian cukup tarik ekstensi yang Anda inginkan.

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
sumber
Itu ide yang buruk. Kode Anda rusak untuk ekstensi file apa pun yang belum Anda tambahkan sebelumnya!
Robert
0

coba ini:

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. dapatkan semua nama file di dalam daftar
  2. memisahkan nama file dan memeriksa ekstensi kedua dari belakang, apakah ada dalam daftar pen_ext atau tidak?
  3. jika ya maka gabungkan dengan ekstensi terakhir dan atur sebagai ekstensi file
  4. jika tidak maka cukup letakkan ekstensi terakhir sebagai ekstensi file
  5. dan kemudian memeriksanya
Ibnul Husainan
sumber
1
Ini istirahat untuk banyak kasus khusus. Lihat jawaban yang diterima. Ini menciptakan kembali roda, hanya dengan cara kereta.
Robert
saya memperbarui jawaban saya
Ibnul Husainan
Halo! Sementara kode ini dapat menyelesaikan pertanyaan, termasuk penjelasan tentang bagaimana dan mengapa ini menyelesaikan masalah akan sangat membantu untuk meningkatkan kualitas posting Anda, dan mungkin menghasilkan lebih banyak suara. Ingatlah bahwa Anda menjawab pertanyaan untuk pembaca di masa depan, bukan hanya orang yang bertanya sekarang. Harap edit jawaban Anda untuk menambahkan penjelasan dan berikan indikasi tentang batasan dan asumsi apa yang berlaku.
Brian
@ Brian seperti itu?
Ibnul Husainan
Anda hanya memperburuknya, memecahkannya dengan cara baru. foo.taradalah nama file yang valid. Apa yang terjadi jika saya melemparkan itu pada kode Anda? Bagaimana dengan .bashrcatau foo? Ada fungsi perpustakaan untuk ini karena suatu alasan ...
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
sumber
-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
pengguna5535053
sumber
-5
name_only=file_name[:filename.index(".")

Itu akan memberi Anda nama file hingga yang pertama ".", Yang akan menjadi yang paling umum.

wookie
sumber
1
pertama, dia tidak perlu nama, tetapi ekstensi. Kedua, bahkan jika ia membutuhkan nama, itu akan salah dengan file seperti:file.name.ext
ya_dimon
Seperti disebutkan oleh @ya_dimon, ini tidak akan berfungsi untuk nama file dengan titik. Plus, dia membutuhkan ekstensi!
Umar Dastgir