Wydobywanie rozszerzenia z nazwy pliku w Pythonie

Odpowiedzi:

1987

Tak. Użyj os.path.splitext(patrz dokumentacja Python 2.X lub dokumentacja Python 3.X ):

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

W przeciwieństwie do większości prób ręcznego dzielenia ciągów, os.path.splitextbędzie poprawnie traktować, /a/b.c/dże nie ma rozszerzenia zamiast rozszerzenia .c/di będzie traktować, .bashrcże nie ma rozszerzenia zamiast rozszerzenia .bashrc:

>>> os.path.splitext('/a/b.c/d')
('/a/b.c/d', '')
>>> os.path.splitext('.bashrc')
('.bashrc', '')
nosklo
źródło
15
użycie basenamejest trochę mylące, ponieważ os.path.basename("/path/to/somefile.ext")wróci"somefile.ext"
Jiaaro
16
nie endswith()nie być bardziej mobilny i pythonic?
Sebastian Mach
79
@ klingt.net Cóż, w takim przypadku, .asdto naprawdę rozszerzenie !! Jeśli się nad tym zastanowić, foo.tar.gzto plik skompresowany gzip ( .gz), który akurat jest plikiem tar ( .tar). Ale to przede wszystkim plik gzip . Nie spodziewałbym się, że w ogóle zwróci podwójne rozszerzenie.
nosklo
157
Standardowa konwencja nazewnictwa funkcji w Pythonie jest naprawdę denerwująca - prawie za każdym razem, gdy to sprawdzam, mylę to jako bycie splittext. Gdyby tylko zrobili coś, co oznaczałoby przerwę między częściami tego imienia, znacznie łatwiej byłoby rozpoznać, że to jest splitExtlub split_ext. Z pewnością nie mogę być jedyną osobą, która popełniła ten błąd?
ArtOfWarfare
9
@ Vingtoft W swoim komentarzu nic nie wspominałeś o FileStorage werkzeug, a to pytanie nie ma nic na temat tego konkretnego scenariusza. Coś może być nie tak z przekazaniem nazwy pliku. os.path.splitext('somefile.ext')=> ('somefile', '.ext'). Nie krępuj się podać rzeczywisty przykład bez odwoływania się do biblioteki innej firmy.
Gewthen
400
import os.path
extension = os.path.splitext(filename)[1]
Brian Neal
źródło
15
Z ciekawości, dlaczego import os.pathzamiast from os import path?
kiswa
2
Och, zastanawiałem się tylko, czy kryje się za tym konkretny powód (inny niż konwencja). Wciąż uczę się języka Python i chciałem dowiedzieć się więcej!
kiswa
55
zależy to naprawdę, jeśli użyjesz, from os import pathto nazwa pathzostanie uwzględniona w twoim zasięgu lokalnym, również inni patrząc na kod mogą nie wiedzieć od razu, że ścieżka jest ścieżką z modułu os. Gdzie, tak jakbyś import os.pathgo używał , utrzymuje go w osprzestrzeni nazw i gdziekolwiek wykonujesz połączenie, ludzie natychmiast wiedzą, że pochodzi path()z osmodułu.
dennmat 24.11.11
18
Wiem, że nie różni się semantycznie inaczej, ale osobiście uważam, że konstrukcja _, extension = os.path.splitext(filename)jest znacznie ładniejsza.
Tim Gilbert,
3
Jeśli chcesz, aby rozszerzenie było częścią bardziej złożonego wyrażenia, [1] może być bardziej użyteczny: if check_for_gzip and os.path.splitext(filename)[1] == '.gz':
gerardw
238

Nowości w wersji 3.4.

import pathlib

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

Dziwię się, nikt nie wspomniano pathlibjednak, pathlibjest niesamowite!

Jeśli potrzebujesz wszystkich przyrostków (np. Jeśli masz .tar.gz), .suffixeszwróci ich listę!

jeromej
źródło
12
przykład uzyskania .tar.gz:''.join(pathlib.Path('somedir/file.tar.gz').suffixes)
user3780389
Świetna odpowiedź. Uważam, że ten samouczek jest bardziej przydatny niż dokumentacja: zetcode.com/python/pathlib
user118967
@ user3780389 Czy „foo.bar.tar.gz” nadal nie byłoby prawidłowym „.tar.gz”? Jeśli tak, Twój fragment kodu powinien być używany, .suffixes[-2:]aby uzyskać tylko .tar.gz.
jeromej
111
import os.path
extension = os.path.splitext(filename)[1][1:]

Aby uzyskać tylko tekst rozszerzenia, bez kropki.

wonzbak
źródło
73

Jedną z opcji może być podział z kropki:

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

Brak błędu, gdy plik nie ma rozszerzenia:

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

Ale musisz uważać:

>>> "png".split(".")[-1]
'png'    # But file doesn't have an extension
Murat Çorlu
źródło
4
To by się zdenerwowało, jeśli przesyłasz x.tar.gz
Kirill
19
Nie aktualne. Rozszerzenie pliku o nazwie „x.tar.gz” to „gz”, a nie „tar.gz”. os.path.splitext podaje również „.os” jako rozszerzenie.
Murat Çorlu
1
czy możemy użyć [1] zamiast [-1]. Nie mogłem zrozumieć [-1] z podziałem
użytkownik765443
7
[-1], aby uzyskać ostatni element przedmiotów podzielonych przez kropkę. Przykład:"my.file.name.js".split('.') => ['my','file','name','js]
Murat Çorlu
1
@BenjaminR ah ok, optymalizujesz listę wyników. ['file', 'tar', 'gz']z 'file.tar.gz'.split('.') vs ['file.tar', 'gz'] z 'file.tar.gz'.rsplit('.', 1). tak, może być.
Murat Çorlu
40

warto dodać tam niższą, abyś nie zastanawiał się, dlaczego pliki JPG nie pojawiają się na liście.

os.path.splitext(filename)[1][1:].strip().lower()
blured
źródło
19

Każde z powyższych rozwiązań działa, ale w systemie Linux odkryłem, że na końcu łańcucha rozszerzenia znajduje się nowa linia, która uniemożliwi pomyślne dopasowanie. Dodaj strip()metodę na końcu. Na przykład:

import os.path
extension = os.path.splitext(filename)[1][1:].strip() 
yamex5
źródło
1
Aby pomóc mi zrozumieć, czy możesz wyjaśnić, przed jakim dodatkowym zachowaniem chroni drugi indeks / segment? (tj. [1:]w .splittext(filename)[1][1:]
środku
1
Zrozumiałem to dla siebie: splittext()(inaczej niż w przypadku podziału łańcucha za pomocą „.”) Zawiera „.” znak w rozszerzeniu. Dodatkowy [1:]się go pozbywa.
Samuel Harmer,
17

Z splitext istnieją problemy z plikami z podwójnym rozszerzeniem (np file.tar.gz, file.tar.bz2itp ..)

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

ale powinno być: .tar.gz

Możliwe rozwiązania są tutaj

XavierCLL
źródło
35
Nie, powinien to być .gz
Robert Siemer
1
zrobić to dwa razy, aby uzyskać 2 rozszerzenia?
maazza
1
@maazza yep. gunzip somefile.tar.gz jaka jest nazwa pliku wyjściowego?
FlipMcF
1
Właśnie dlatego mamy rozszerzenie „tgz”, co oznacza: tar + gzip! : D
Nuno Aniceto
1
@peterhil Nie sądzę, że chcesz, aby twój skrypt pythonowy był świadomy aplikacji użytej do utworzenia nazwy pliku. To trochę poza zakresem pytania. Nie wybieraj tego przykładu, „filename.csv.gz” jest również całkiem poprawny.
FlipMcF
16

Możesz znaleźć świetne rzeczy w module pathlib (dostępnym w Pythonie 3.x).

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

# Output 
'.txt'
r3t40
źródło
14

Chociaż jest to stary temat, ale zastanawiam się, dlaczego w tym przypadku nie wspomina się o bardzo prostym interfejsie API Pythona o nazwie rpartition:

aby uzyskać rozszerzenie ścieżki bezwzględnej dla danego pliku, możesz po prostu wpisać:

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

przykład:

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

da ci: „csv”

weiyixie
źródło
1
Dla tych, którzy nie są zaznajomieni z API, rpartition zwraca krotki: ("string before the right-most occurrence of the separator", "the separator itself", "the rest of the string"). Jeśli nie znaleziono żadnego separator, zwrócony krotka będzie: ("", "", "the original string").
Nickolay
13

Po prostu joinwszystko 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
źródło
12

Zaskoczony, że jeszcze nie wspomniano:

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

Korzyści:

  • Działa zgodnie z oczekiwaniami dla wszystkiego, co mogę wymyślić
  • Brak modułów
  • Brak wyrażenia regularnego
  • Międzyplatformowy
  • Łatwo rozszerzalny (np. Brak wiodących kropek do przedłużenia, tylko ostatnia część przedłużenia)

Jako funkcja:

def get_extension(filename):
    basename = os.path.basename(filename)  # os independent
    ext = '.'.join(basename.split('.')[1:])
    return '.' + ext if ext else None
PascalVKooten
źródło
1
Powoduje to wyjątek, gdy plik nie ma żadnego rozszerzenia.
thiruvenkadam
4
Ta odpowiedź absolutnie ignoruje wariant, jeśli nazwa pliku zawiera wiele punktów w nazwie. Przykład get_extension ('cmocka-1.1.0.tar.xz') => '.1.0.tar.xz' - źle.
PADYMKO,
@PADYMKO, IMHO nie należy tworzyć nazw plików z kropkami jako części nazwy pliku. Powyższy kod nie powinien powodować „tar.xz”
Douwe van der Leest
2
Po prostu przejdź do [-1]tego.
PascalVKooten
11

Możesz użyć splitna filename:

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

Nie wymaga to dodatkowej biblioteki

soheshdoshi
źródło
10
filename='ext.tar.gz'
extension = filename[filename.rfind('.'):]
czas pobytu
źródło
2
Powoduje filenameto zwrócenie ostatniego znaku , jeśli nazwa pliku w ogóle go nie ma .. Jest tak, ponieważ rfindzwraca, -1jeśli ciąg nie zostanie znaleziony.
mattst
6

Jest to technika bezpośredniej reprezentacji ciągu: widzę wiele wspomnianych rozwiązań, ale myślę, że większość szuka podziału. Podziel jednak robi to przy każdym wystąpieniu „.” . To, czego wolisz, to partycja.

string = "folder/to_path/filename.ext"
extension = string.rpartition(".")[-1]
Kenstars
źródło
2
rpartition został już zasugerowany przez @weiyixie .
Nickolay
5

Inne rozwiązanie z odpowiednim podziałem:

# 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
źródło
5

Nawet na to pytanie już udzielono odpowiedzi, dodałbym rozwiązanie w Regex.

>>> import re
>>> file_suffix = ".*(\..*)"
>>> result = re.search(file_suffix, "somefile.ext")
>>> result.group(1)
'.ext'
Micha
źródło
1
Lub \.[0-9a-z]+$jak w tym poście .
paul
2

Prawdziwy jednowarstwowy, jeśli lubisz wyrażenia regularne. I to nie ma znaczenia, nawet jeśli masz dodatkowe „”. pośrodku

import re

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

Zobacz wynik: Kliknij tutaj

Victor Wang
źródło
0

Jest to najprostsza metoda uzyskania zarówno nazwy pliku, jak i rozszerzenia w jednym wierszu .

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

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

W przeciwieństwie do innych rozwiązań, nie musisz zaimportować do tego żadnego pakietu.

Ripon Kumar Saha
źródło
2
to nie działa dla wszystkich plików lub typów, na przykład „archive.tar.gz
studioj
0

Dla miłośników ... po prostu zbierz rozszerzenia w nagraniu i śledź je wszystkie w folderze. Następnie po prostu wyciągnij odpowiednie rozszerzenia.

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
źródło
To okropny pomysł. Twój kod ulega uszkodzeniu dla każdego rozszerzenia, którego wcześniej nie dodałeś!
Robert
0

Spróbuj tego:

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. pobierz całą nazwę pliku z listy
  2. dzielenie nazwy pliku i sprawdzanie przedostatniego rozszerzenia, czy jest ono na liście tekstów pen_ext, czy nie?
  3. jeśli tak, to dołącz do ostatniego rozszerzenia i ustaw jako rozszerzenie pliku
  4. jeśli nie, to po prostu wstaw ostatnie rozszerzenie jako rozszerzenie pliku
  5. a następnie sprawdź
Ibnul Husainan
źródło
1
To załamuje się w przypadku kilku specjalnych przypadków. Zobacz zaakceptowaną odpowiedź. Wymyśla koło na nowo, tylko w powozikach.
Robert
zaktualizowałem swoją odpowiedź
Ibnul Husainan
Dzień dobry! Chociaż ten kod może rozwiązać pytanie, w tym wyjaśnienie, w jaki sposób i dlaczego to rozwiązuje problem, naprawdę pomógłby poprawić jakość twojego postu i prawdopodobnie doprowadziłby do większej liczby głosów. Pamiętaj, że odpowiadasz na pytanie dla czytelników w przyszłości, nie tylko dla osoby zadającej teraz pytanie. Proszę edytować swoje odpowiedzi, aby dodać wyjaśnień i dać wskazówkę co zastosować ograniczenia i założenia.
Brian
@Brian tak?
Ibnul Husainan
Tylko pogarszasz to, przełamując to na nowe sposoby. foo.tarjest prawidłową nazwą pliku. Co się stanie, jeśli wyrzucę to na twój kod? Co z .bashrclub foo? Z tego powodu istnieje funkcja biblioteki ...
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
źródło
-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
użytkownik5535053
źródło
-5
name_only=file_name[:filename.index(".")

To da ci nazwę pliku do pierwszego „.”, Który byłby najczęstszy.

wookie
źródło
1
po pierwsze, nie potrzebuje nazwy, ale rozszerzenia. Po drugie, nawet gdyby potrzebował imienia, byłoby błędne w plikach takich jak:file.name.ext
ya_dimon
Jak wspomniano przez @ya_dimon, nie będzie to działać w przypadku nazw plików z kropkami. Dodatkowo potrzebuje rozszerzenia!
Umar Dastgir,