Ответы:
Использование 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 функции split относительно вашего пути или ОС.
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'[^\\/]+(?![\\/])$'. Для "regex challengeed" это изменяет положительный прогноз прямого просмотра для некоторого вида косой черты на отрицательный прямой взгляд вперед, в результате чего имена путей, заканчивающиеся указанным слешем, ничего не возвращают вместо последнего подкаталога в имени пути. Конечно, нет никакой гарантии, что потенциальное имя файла на самом деле относится к файлу и для этого 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'/'.