Витяг розширення з імені файлу в Python


Відповіді:


1988

Так. Використовуйте os.path.splitext(див. Документацію Python 2.X або документацію Python 3.X ):

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

На відміну від більшості спроб розбиття рядків вручну, os.path.splitextбуде правильно вважати /a/b.c/d, що не має розширення, а не розширення .c/d, і вважатиме .bashrc, що не має розширення замість розширення .bashrc:

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

15
використання basenameтут трохи заплутане, оскільки os.path.basename("/path/to/somefile.ext")повернеться"somefile.ext"
Jiaaro

17
не endswith()були б більш портативними та пітонічними?
Себастьян Мах

79
@ klingt.net Ну, у цьому випадку .asdце дійсно розширення !! Якщо ви задумаєтесь про це, foo.tar.gz- це файл, стиснутий gzip ( .gz), який, можливо, є файлом tar ( .tar). Але це gzip-файл в першу чергу. Я б не очікував, що він взагалі поверне подвійне розширення.
nosklo

158
Стандартна умова іменування функції Python насправді дратує - майже кожного разу, коли я переглядаю це, я помиляюсь як таке splittext. Якби вони просто зробили що-небудь для позначення розриву між частинами цього імені, було б набагато простіше визнати, що це splitExtчи split_ext. Звичайно, я не можу бути єдиною людиною, яка допустила цю помилку?
ArtOfWarfare

9
@Vingtoft У коментарі ви нічого не згадували про FileStorage werkzeug, і це питання нічого не стосується конкретного сценарію. Щось може бути не так у тому, як вам передано ім’я файлу. os.path.splitext('somefile.ext')=> ('somefile', '.ext'). Не соромтеся навести фактичний приклад лічильника, не посилаючись на якусь сторонній бібліотеку.
Gewthen

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

15
Чому з цікавості, чому import os.pathзамість цього from os import path?
kiswa

2
О, мені просто було цікаво, чи є за нею певна причина (крім конвенції). Я ще вивчаю Python і хотів дізнатися більше!
kiswa

55
Це дійсно залежить, якщо ви використовуєте, from os import pathто ім'я pathміститься у вашому локальному масштабі, також інші, хто дивиться на код, можуть не відразу знати, що шлях - це шлях від модуля os. Якщо ніби ви import os.pathйого використовуєте, він зберігає його в osпросторі імен, і де б ви не телефонували, люди знають, що це path()з osмодуля негайно.
dennmat

18
Я знаю, що це не семантично інакше, але я особисто вважаю конструкцію _, extension = os.path.splitext(filename)набагато приємнішою.
Тім Гілберт

3
Якщо ви хочете, щоб розширення було частиною більш складного виразу, [1] може бути кориснішим: if check_for_gzip and os.path.splitext(filename)[1] == '.gz':
gerardw

238

Нове у версії 3.4.

import pathlib

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

Я здивований, що ніхто ще не згадав pathlib, pathlibце дивовижно!

Якщо вам потрібні всі суфікси (наприклад, якщо у вас є .tar.gz), .suffixesповернете їх список!


12
Приклад отримання .tar.gz:''.join(pathlib.Path('somedir/file.tar.gz').suffixes)
user3780389

Чудова відповідь. Я вважаю цей підручник кориснішим, ніж документація: zetcode.com/python/pathlib
user118967

@ user3780389 Чи не "foo.bar.tar.gz" все ще є дійсним ".tar.gz"? Якщо так, ваш фрагмент повинен використовуватись .suffixes[-2:]для забезпечення лише отримання .tar.gz.
jeromej

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

Щоб отримати лише текст розширення, без крапки.


73

Один варіант може бути розщепленням від точки:

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

Немає помилки, коли файл не має розширення:

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

Але ви повинні бути обережними:

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

4
Це засмутиться, якщо ви завантажуєте x.tar.gz
Кирилл

19
Насправді. Розширення файлу з назвою "x.tar.gz" - це "gz", а не "tar.gz". os.path.splitext надає ".os" як розширення.
Мурат Чорлу

1
чи можемо ми використовувати [1], а не [-1]. Я не міг зрозуміти [-1] зі спліт
user765443

7
[-1], щоб отримати останній елемент елементів, розбитий крапкою. Приклад:"my.file.name.js".split('.') => ['my','file','name','js]
Мурат Чорлу

1
@BenjaminR ах добре, ви оптимізуєте список результатів. ['file', 'tar', 'gz']з 'file.tar.gz'.split('.') vs ['file.tar', 'gz'] з 'file.tar.gz'.rsplit('.', 1). так, могло бути.
Murat Çorlu

40

Варто додати там нижче, щоб вам не цікаво, чому JPG не відображаються у вашому списку.

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

19

Будь-яке з вищезазначених рішень працює, але на Linux я виявив, що в кінці рядка розширення є новий рядок, який запобігає успіху матчів. Додайте strip()метод до кінця. Наприклад:

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

1
Щоб допомогти мені зрозуміти, будь-ласка, поясніть, проти якої поведінки захищає другий індекс / фрагмент? (тобто [1:]в .splittext(filename)[1][1:]) - дякую заздалегідь
Самуель Хармер

1
Я зрозумів це для себе: splittext()(на відміну від того, якщо ви розділили рядок, використовуючи ".") Включає "." персонаж у розширенні. Додатковий [1:]позбавляється від цього.
Семюел Хармер

17

З splitext виникають проблеми з файлами з подвійним розширенням (наприклад file.tar.gz, file.tar.bz2і т. Д. )

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

але має бути: .tar.gz

Можливі рішення тут


35
Ні, це має бути .gz
Роберт Сімер

1
зробити це двічі, щоб отримати 2 розширення?
maazza

1
@maazza так. gunzip somefile.tar.gz яке вихідне ім'я файлу?
FlipMcF

1
Ось чому у нас є розширення 'tgz', що означає: tar + gzip! : D
Nuno Aniceto

1
@peterhil Я не думаю, що ви хочете, щоб ваш сценарій python знав про програму, яка використовується для створення імені файлу. Це трохи поза сферою питання. Не вибирайте на прикладі, "filename.csv.gz" також цілком справедливий.
FlipMcF

16

У модулі pathlib можна знайти кілька чудових матеріалів (доступних у python 3.x).

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

# Output 
'.txt'

14

Хоча це давня тема, але мені цікаво, чому в цій справі немає жодної згадки про дуже простий api python під назвою rpartition:

щоб отримати розширення даного файлу абсолютного шляху, ви можете просто ввести:

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

приклад:

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

дасть вам: 'csv'


1
Для тих , хто не знайомий з API, rpartition повертає кортеж: ("string before the right-most occurrence of the separator", "the separator itself", "the rest of the string"). Якщо немає роздільник знайдений, то повертається кортеж буде: ("", "", "the original string").
Миколай

13

Просто joinвсі 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

Дивно, що про це ще не згадували:

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

Переваги:

  • Працює так, як очікувалося, для всього, що я можу придумати
  • Немає модулів
  • Без регексу
  • Крос-платформа
  • Легко розширюваний (наприклад, відсутні провідні точки для розширення, лише остання частина розширення)

Як функція:

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

1
Це призводить до виключення, коли файл не має жодного розширення.
thiruvenkadam

4
Ця відповідь абсолютно ігнорує варіант, якщо ім'я файлу містить багато точок в імені. Приклад get_extension ('cmocka-1.1.0.tar.xz') => '.1.0.tar.xz' - неправильно.
ПАДИМКО

@PADYMKO, IMHO не слід створювати назви файлів з повними зупинками як частину імені файлу. Наведений вище код не повинен приводити до "tar.xz"
Douwe van der

2
Просто змініть на [-1]потім.
PascalVKooten

11

Ви можете використовувати splitна filename:

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

Для цього не потрібна додаткова бібліотека


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

2
Це призводить до filenameповернення останнього символу , якщо ім'я файлу взагалі немає .. Це тому, що rfindповертається, -1якщо рядок не знайдено.
матст

6

Це методи прямого представлення рядків: я бачу багато згаданих рішень, але думаю, що більшість дивиться на розкол. Розділення, однак, робить це при кожному виникненні "". . Що ви хотіли б шукати - це розділ.

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

2
rpartition вже запропонував @weiyixie .
Миколай

5

Ще одне рішення з правильним розділенням:

# 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

Навіть на це питання вже відповіли, я б додав рішення в Regex.

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

1
Або \.[0-9a-z]+$як у цій публікації .
pault

2

Справжній однолінійний, якщо вам подобається регулярний вираз. І це не має значення, навіть якщо у вас є додаткові "". посередині

import re

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

Ознайомтеся з результатом: натисніть тут


0

Це найпростіший метод отримати як ім'я файлу, так і розширення лише в одному рядку .

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

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

На відміну від інших рішень, вам не потрібно імпортувати жоден пакет для цього.


2
це не працює для всіх файлів або типів, наприклад 'archive.tar.gz
studioj

0

Для прихильників ... просто збирайте розширення в дікт і відстежуйте їх у папці. Потім просто потягніть потрібні розширення.

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)

Це жахлива ідея. Ваш код порушується для будь-якого розширення файлу, якого ви раніше не додавали!
Роберт

0

спробуйте це:

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. отримати все ім’я файлу всередині списку
  2. розділіть назву файлу та перевірте передостаннє розширення, чи є він у списку pen_ext чи ні?
  3. якщо так, то приєднайте його до останнього розширення та встановіть його як розширення файлу
  4. якщо ні, то просто поставте останнє розширення як розширення файлу
  5. а потім перевірити це

1
Це перерва на купу особливих справ. Дивіться прийняту відповідь. Це винахід за кермом, тільки у баггі.
Роберт

я оновив свою відповідь
Ibnul Husainan

Привіт! Хоча цей код може вирішити питання, включаючи пояснення, як і чому це вирішує проблему, справді допоможе покращити якість вашої публікації та, ймовірно, призведе до збільшення кількості голосів. Пам'ятайте, що ви відповідаєте на запитання читачів у майбутньому, а не лише про людину, яка зараз задає питання. Будь ласка, відредагуйте свою відповідь, щоб додати пояснення та вказати, які обмеження та припущення застосовуються.
Брайан


Ти тільки погіршуєшся, ламаєш це по-новому. foo.tar- дійсне ім'я файлу. Що станеться, якщо я кину це на ваш код? Що про .bashrcабо foo? Для цього є функція бібліотеки з якоїсь причини ...
Роберт

-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(".")

Це дасть вам ім'я файлу до першого ".", Яке було б найпоширенішим.


1
по-перше, йому потрібно не ім’я, а розширення. По-друге, навіть якщо йому буде потрібно ім'я, це було б неправильно в таких файлах, як:file.name.ext
ya_dimon

Як згадував @ya_dimon, ця робота не працює для імен файлів з крапками. Плюс йому потрібне розширення!
Умар
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.