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', '')

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]

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ę!


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.


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

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

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

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


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'

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”


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'

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

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


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

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]

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])

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'

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


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.


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)

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ź

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 ""

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

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


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,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.