Какую библиотеку Python я могу использовать для извлечения имен файлов из путей, независимо от операционной системы или формата пути?
Например, я хотел бы, чтобы все эти пути возвращали мне c
:
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
На самом деле, там'ы функция, который возвращает именно то, что вы хотите
import os
print(os.path.basename(your_path))
Использование os.path.split
или os.path.basename
, как советуют другие, будет работать не во всех случаях: если вы запустите скрипт в Linux и попытаетесь обработать классический путь в стиле windows, он потерпит неудачу.
В путях Windows в качестве разделителя путей может использоваться обратная или прямая косая черта. Поэтому модуль ntpath
(который эквивалентен os.path при работе на windows) будет работать для всех(1) путей на всех платформах.
import ntpath
ntpath.basename("a/b/c")
Конечно, если файл заканчивается слэшем, имя basename будет пустым, поэтому сделайте собственную функцию, чтобы справиться с этим:
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, но помните об этом при написании кода, чтобы не создавать случайных дыр в безопасности.
os.path.split это функция, которую вы ищете
head, tail = os.path.split("/tmp/d/a.dat")
>>> print(tail)
a.dat
>>> print(head)
/tmp/d
import os
head, tail = os.path.split(p)
print tail
Предположим, что p - это входная строка, tail - это то, что вам нужно.
Подробности см. в Документах по модулю python os.
В вашем примере Вам также потребуется прокладка Слэш справа правой стороне, чтобы вернуться "с":
>>> 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.
fname = str("C:\Windows\paint.exe").split('\\')[-1:][0]
это вернется : paint.exe
изменить значение сентября функции Split относительно вашего пути или OS.
Это работает для 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 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]))
Вы можете объединить обе в одну функцию проверить тип ОС и вернуть результат.
Здесь'ы в regex-единственное решение, которое, кажется, работает с любыми путь ОС на любой ОС.
Никакой другой модуль, и без предварительной обработки, необходимо либо :
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/Б/ - это Дир и так
c:\windows`), изменить регулярное выражение: Р'[^\\/]+(?![\\/])$'
. За "и выражение оспорены," эта изменяет положительный просмотр вперед для какой-то Слэш отрицательный просмотр вперед, вызывая путей, которые оканчиваются сказал Слэш вернуть ничего вместо последнего подкаталога в пути. Конечно, нет никакой гарантии, что потенциал именем на самом деле относится к файлу и за это ОС.путь.is_dir()или
ОС.путь.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
Регулярное выражение может быть проверена здесь.
питон импорт ОС file_location = '/СРВ/том1/данные/ЭЦП/eds_report.КШМ' имя_файла = ОС.путь.и basename(file_location ) #eds_report.КШМ расположение = ОС.путь.каталог(file_location ) #/СРВ/том1/данные/ЭЦП
Я никогда не видел двойной управляющими пути, они существуют? Встроенный в модуль Python ОС
не для тех. Все остальные работы, кроме той оговоркой, приведенные вами с ОС.путь.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))
Разделитель окна могут быть в имени файла 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])
Может просто у меня все в одном решение, не важно, новые(в связи с tempfile для создания временных файлов :Д )
import tempfile
abc = tempfile.NamedTemporaryFile(dir='/tmp/')
abc.name
abc.name.replace("/", " ").split()[-1]
Получение значений азбуки.название будет строка типа этой: '/tmp/и tmpks5oksk7'
Так что я могу заменить /
с места .заменить (на"/" и " Ну и")
, а затем вызвать сплит()
. Который будет возвращать список, и я получаю
последний элемент списка [-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=правда
. Это позволит разбить входную строку на части, последний лист, который вы ищете, следовательно, path2unix(Т)[-1]
.
Если nojoin аргумент =false
, то путь будет присоединить обратно, так что выход-это просто входной строки преобразовать в Unix-формате, которые могут быть полезны для сравнения подпутей на разных платформах.