Answers:
使用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文件名中很少使用反斜杠,但是在编写代码时请记住这一点,以免造成意外的安全漏洞。
r'C:\path\to\file.txt'
在Linux机器上解析Windows样式路径(例如)时,才需要使用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
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
已经提供了正确的答案。我的代码不适用于unix系统上类似Windows的路径,反之亦然,不适用于Windows系统上类似unix的路径。
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]))
您可以通过检查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']
这是仅用于正则表达式的解决方案,它似乎可与任何OS上的任何OS路径一起使用。
不需要其他模块,也不需要预处理:
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/
dir,也是如此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机器上也可以处理路径分隔符。对于Linux,该posixpath
模块(resp。os.path
)将简化路径操作,仅允许使用posix样式'/'
分隔符。