Извлечение имени файла из пути, независимо от того, какой формат os / path - PullRequest
596 голосов
/ 05 декабря 2011

Какую библиотеку 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

Ответы [ 15 ]

967 голосов
/ 05 декабря 2011

На самом деле, есть функция , которая возвращает именно то, что вы хотите

print(os.path.basename(your_path))
625 голосов
/ 05 декабря 2011

Использование os.path.split или os.path.basename, как предлагают другие, не будет работать во всех случаях: если вы запускаете сценарий в Linux и пытаетесь обработать классический путь в стиле Windows, он потерпит неудачу.

Пути Windows могут использовать либо обратную косую черту, либо прямую косую черту в качестве разделителя пути. Поэтому модуль ntpath (который при запуске в Windows эквивалентен os.path) будет работать для всех путей (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 обратная косая черта редко используется, но помните об этом при кодировании, чтобы не создавать случайные дыры в безопасности.

187 голосов
/ 05 декабря 2011

os.path.split - это функция, которую вы ищете

head, tail = os.path.split("/tmp/d/a.dat")

>>> print(tail)
a.dat
>>> print(head)
/tmp/d
42 голосов
/ 03 февраля 2018

В питоне 3

>>> from pathlib import Path    
>>> Path("/tmp/d/a.dat").name
'a.dat'
34 голосов
/ 05 декабря 2011
import os
head, tail = os.path.split(p)
print tail

Предположим, что p - это входная строка, а tail - то, что вы хотите.

См. документы по Python OS Module для подробностей

11 голосов
/ 05 декабря 2011

В вашем примере вам также нужно убрать косую черту справа и справа, чтобы вернуть 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-системах.

8 голосов
/ 03 ноября 2014
fname = str("C:\Windows\paint.exe").split('\\')[-1:][0]

это вернет: paint.exe

измените значение sep функции разделения относительно вашего пути или ОС.

7 голосов
/ 18 июня 2015

Это работает для 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']
6 голосов
/ 19 февраля 2019

Если путь к файлу не заканчивается символом "/", а каталоги разделены символом "/", используйте следующий код.Как мы знаем, обычно путь не заканчивается на "/".

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

Вы можете объединить обе функции в одну функцию, проверив тип ОС и вернув результат.

5 голосов
/ 28 ноября 2016

Вот решение, предназначенное только для регулярных выражений, которое, похоже, работает с любым путем к ОС в любой ОС.

Никаких других модулей не требуется, и предварительная обработка не требуется:

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" это меняет положительный прогноз вперед для своего рода слеш на отрицательный прогноз вперед, в результате чего имена путей, оканчивающиеся на slash , ничего не возвращают вместо последнегоподкаталог в пути.Конечно, нет никакой гарантии, что имя файла потенциальная на самом деле ссылается на файл, и для этого потребуется использовать 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

Регулярное выражение можно проверить здесь .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...