Відповіді:
Використання os.path.splitабо os.path.basenameяк вважають інші, не буде працювати у всіх випадках: якщо ви запускаєте скрипт в Linux і намагаєтеся обробити класичний шлях у стилі Windows, він не вдасться.
Шляхи для Windows можуть використовувати як зворотний кут нахилу або нахил вперед як роздільник шляхів. Тому ntpathмодуль (що еквівалентно os.path при запуску на Windows) буде працювати для всіх (1) шляхів на всіх платформах.
import ntpath
ntpath.basename("a/b/c")
Звичайно, якщо файл закінчується косою рисою, базове ім’я буде порожнім, тому зробіть власну функцію для вирішення цього питання:
def path_leaf(path):
head, tail = ntpath.split(path)
return tail or ntpath.basename(head)
Підтвердження:
>>> paths = ['a/b/c/', 'a/b/c', '\\a\\b\\c', '\\a\\b\\c\\', 'a\\b\\c',
... 'a/b/../../a/b/c/', 'a/b/../../a/b/c']
>>> [path_leaf(path) for path in paths]
['c', 'c', 'c', 'c', 'c', 'c', 'c']
(1) Є одне застереження: назви файлів Linux можуть містити зворотні риски . Так що в linux r'a/b\c'завжди посилається на файл b\cу aпапці, тоді як у Windows він завжди посилається на cфайл у bпідпапці aпапки. Тож, коли як прямі, так і зворотні косої риси використовуються в шляху, вам потрібно знати пов'язану платформу, щоб мати можливість її правильно інтерпретувати. На практиці, як правило, можна припустити, що це шлях до Windows, оскільки в назви файлів Linux рідко застосовуються кососуші риски, але пам’ятайте про це, коли кодуєте, щоб не створювати випадкових дірок у захисті.
r'C:\path\to\file.txt') на машині Linux, потрібно використовувати модуль ntpath. В іншому випадку ви можете використовувати функції від os.path. Це пов’язано з тим, що системи Linux зазвичай дозволяють використовувати символи зворотної косої риски у назви файлів (як пояснено у відповіді).
os.path.basename(os.path.normpath(path))?
Насправді є функція, яка повертає саме те, що ви хочете
import os
print(os.path.basename(your_path))
os.path.basename(your_path)Це спрацювало! Я хотів шлях сценарію: os.path.dirname(os.path.realpath(__file__))і ім'я скрипта: os.path.basename(os.path.realpath(__file__)). Дякую!
'C:\\temp\\bla.txt'натомість.
os.path.split - це функція, яку ви шукаєте
head, tail = os.path.split("/tmp/d/a.dat")
>>> print(tail)
a.dat
>>> print(head)
/tmp/d
У пітоні 3
>>> from pathlib import Path
>>> Path("/tmp/d/a.dat").name
'a.dat'
import os
head, tail = os.path.split('path/to/file.exe')
хвіст - це те, що ви хочете, ім'я файлу.
Докладніше див. Документи до модуля python os
import os
file_location = '/srv/volume1/data/eds/eds_report.csv'
file_name = os.path.basename(file_location ) #eds_report.csv
location = os.path.dirname(file_location ) #/srv/volume1/data/eds
У вашому прикладі вам також потрібно буде зняти косу рису з правого правого боку, щоб повернутися c:
>>> import os
>>> path = 'a/b/c/'
>>> path = path.rstrip(os.sep) # strip the slash from the right side
>>> os.path.basename(path)
'c'
Другий рівень:
>>> os.path.filename(os.path.dirname(path))
'b'
оновлення: я думаю, що lazyrвін дав правильну відповідь. Мій код не працюватиме з Windows-подібними доріжками в системах Unix і навпаки з unix-подібними шляхами в системі Windows.
r"a\b\c"ні на Linux, ні "a/b/c"на Windows.
os.path.basename(path)буде працювати , тільки якщо os.path.isfile(path)є True. Тому path = 'a/b/c/'взагалі
os.path.basename("a/b/c/")повертається ""через проділ.
lazyrти правий! Я про це не думав. Чи було б безпечно це зробити path = path.replace('\\', '/')?
fname = str("C:\Windows\paint.exe").split('\\')[-1:][0]
це повернеться: paint.exe
змінити значення sep розбитої функції стосовно вашого шляху чи ОС.
fname = str(path).split('/')[-1]
Якщо ваш шлях до файлу не закінчився "/", а каталоги розділені "/", тоді використовуйте наступний код. Як ми знаємо, звичайно шлях не закінчується на "/".
import os
path_str = "/var/www/index.html"
print(os.path.basename(path_str))
Але в деяких випадках, наприклад, URL-адреси закінчуються на "/", тоді використовуйте наступний код
import os
path_str = "/home/some_str/last_str/"
split_path = path_str.rsplit("/",1)
print(os.path.basename(split_path[0]))
але коли ваш шлях прописаний символом "\", який ви зазвичай знаходите у шляхах до Windows, то ви можете використовувати наступні коди
import os
path_str = "c:\\var\www\index.html"
print(os.path.basename(path_str))
import os
path_str = "c:\\home\some_str\last_str\\"
split_path = path_str.rsplit("\\",1)
print(os.path.basename(split_path[0]))
Ви можете об'єднати обидві функції в одній функції, перевіривши тип ОС і повернути результат.
Це працює для Linux та Windows, а також зі стандартною бібліотекою
paths = ['a/b/c/', 'a/b/c', '\\a\\b\\c', '\\a\\b\\c\\', 'a\\b\\c',
'a/b/../../a/b/c/', 'a/b/../../a/b/c']
def path_leaf(path):
return path.strip('/').strip('\\').split('/')[-1].split('\\')[-1]
[path_leaf(path) for path in paths]
Результати:
['c', 'c', 'c', 'c', 'c', 'c', 'c']
Ось рішення, призначене лише для регулярних виразів, яке, здається, працює з будь-яким шляхом до будь-якої ОС.
Жоден інший модуль не потрібен, і попередня обробка також не потрібна:
import re
def extract_basename(path):
"""Extracts basename of a given path. Should Work with any OS Path on any OS"""
basename = re.search(r'[^\\/]+(?=[\\/]?$)', path)
if basename:
return basename.group(0)
paths = ['a/b/c/', 'a/b/c', '\\a\\b\\c', '\\a\\b\\c\\', 'a\\b\\c',
'a/b/../../a/b/c/', 'a/b/../../a/b/c']
print([extract_basename(path) for path in paths])
# ['c', 'c', 'c', 'c', 'c', 'c', 'c']
extra_paths = ['C:\\', 'alone', '/a/space in filename', 'C:\\multi\nline']
print([extract_basename(path) for path in extra_paths])
# ['C:', 'alone', 'space in filename', 'multi\nline']
Оновлення:
Якщо ви хочете лише потенційне ім'я файлу, якщо воно є (тобто/a/b/ є реж і так c:\windows\), змінити регулярний вираз: r'[^\\/]+(?![\\/])$'. Для "регулярного виклику, оскарженого", це змінює позитивну пряму позицію вперед для деякого роду косою рисою на негативну вперед лококахед, внаслідок чого назви шляхів, що закінчуються зазначеною косою рисою, не повертають нічого замість останнього підкаталогу в імені шляху. Звичайно, немає гарантії, що потенційне ім'я файлу насправді посилається на файл і для цього os.path.is_dir()або os.path.is_file()його потрібно буде використовувати.
Це буде відповідати наступним чином:
/a/b/c/ # nothing, pathname ends with the dir 'c'
c:\windows\ # nothing, pathname ends with the dir 'windows'
c:hello.txt # matches potential filename 'hello.txt'
~it_s_me/.bashrc # matches potential filename '.bashrc'
c:\windows\system32 # matches potential filename 'system32', except
# that is obviously a dir. os.path.is_dir()
# should be used to tell us for sure
Регекс можна перевірити тут .
Можливо, просто моє все в одному рішенні без важливого нового (врахуйте тимчасовий файл для створення тимчасових файлів: D)
import tempfile
abc = tempfile.NamedTemporaryFile(dir='/tmp/')
abc.name
abc.name.replace("/", " ").split()[-1]
Отримання значень abc.nameбуде таким рядком: '/tmp/tmpks5oksk7'
Отже, я можу замінити /пробіл, .replace("/", " ")а потім зателефонуватиsplit() . Це поверне список, і я отримаю останній елемент списку[-1]
Не потрібно імпортувати жоден модуль.
Я ніколи не бачив шляхів з подвійною косою рисою, вони існують? Вбудована функція модуля python osне спрацьовує. Всі інші працюють, також застереження, яке ви даєте os.path.normpath():
paths = ['a/b/c/', 'a/b/c', '\\a\\b\\c', '\\a\\b\\c\\', 'a\\b\\c',
... 'a/b/../../a/b/c/', 'a/b/../../a/b/c', 'a/./b/c', 'a\b/c']
for path in paths:
os.path.basename(os.path.normpath(path))
Розділювач Windows може містити ім'я файлу Unix або Шлях Windows. Розділювач Unix може існувати лише у шляху Unix. Наявність роздільника Unix вказує на шлях, який не стосується Windows.
Далі буде викреслено (вирізати кінцевий роздільник) певним розділювачем ОС, потім розділити та повернути найправіше значення. Це некрасиво, але просто, грунтуючись на припущенні вище. Якщо припущення неправильне, будь ласка, оновіть, і я оновлю цю відповідь, щоб відповідати більш точним умовам.
a.rstrip("\\\\" if a.count("/") == 0 else '/').split("\\\\" if a.count("/") == 0 else '/')[-1]
зразок коду:
b = ['a/b/c/','a/b/c','\\a\\b\\c','\\a\\b\\c\\','a\\b\\c','a/b/../../a/b/c/','a/b/../../a/b/c']
for a in b:
print (a, a.rstrip("\\" if a.count("/") == 0 else '/').split("\\" if a.count("/") == 0 else '/')[-1])
Для повноти, ось pathlibрішення для python 3.2+:
>>> from pathlib import PureWindowsPath
>>> paths = ['a/b/c/', 'a/b/c', '\\a\\b\\c', '\\a\\b\\c\\', 'a\\b\\c',
... 'a/b/../../a/b/c/', 'a/b/../../a/b/c']
>>> [PureWindowsPath(path).name for path in paths]
['c', 'c', 'c', 'c', 'c', 'c', 'c']
Це працює і в Windows, і в Linux.
І в Python 2 і 3, використовуючи модуль pathlib2 :
import posixpath # to generate unix paths
from pathlib2 import PurePath, PureWindowsPath, PurePosixPath
def path2unix(path, nojoin=True, fromwinpath=False):
"""From a path given in any format, converts to posix path format
fromwinpath=True forces the input path to be recognized as a Windows path (useful on Unix machines to unit test Windows paths)"""
if not path:
return path
if fromwinpath:
pathparts = list(PureWindowsPath(path).parts)
else:
pathparts = list(PurePath(path).parts)
if nojoin:
return pathparts
else:
return posixpath.join(*pathparts)
Використання:
In [9]: path2unix('lala/lolo/haha.dat')
Out[9]: ['lala', 'lolo', 'haha.dat']
In [10]: path2unix(r'C:\lala/lolo/haha.dat')
Out[10]: ['C:\\', 'lala', 'lolo', 'haha.dat']
In [11]: path2unix(r'C:\lala/lolo/haha.dat') # works even with malformatted cases mixing both Windows and Linux path separators
Out[11]: ['C:\\', 'lala', 'lolo', 'haha.dat']
З вашою тестовою шкалою:
In [12]: testcase = paths = ['a/b/c/', 'a/b/c', '\\a\\b\\c', '\\a\\b\\c\\', 'a\\b\\c',
...: ... 'a/b/../../a/b/c/', 'a/b/../../a/b/c']
In [14]: for t in testcase:
...: print(path2unix(t)[-1])
...:
...:
c
c
c
c
c
c
c
Ідея тут полягає в перетворенні всіх контурів в єдине внутрішнє представлення pathlib2, з різними декодерами залежно від платформи. На щастя, pathlib2включає загальний декодер, який називається, PurePathякий повинен працювати на будь-якому шляху. Якщо це не працює, ви можете примусити розпізнати шлях Windows за допомогою fromwinpath=True. Це розділить вхідний рядок на частини, останній - лист, який ви шукаєте, отже path2unix(t)[-1].
Якщо аргумент nojoin=False, шлях буде приєднаний назад, так що вихід є просто вхідним рядком, перетвореним у формат Unix, який може бути корисним для порівняння підпутрів на різних платформах.
os.pathпросто завантажуєntpathмодуль всередину. За допомогою цього модуля можна обробляти'\\'роздільники шляху навіть на машинах Linux. Для Linuxposixpathмодуль (респ.os.path) Спростить операції шляху, дозволяючи лише роздільники стилів posix'/'.