无论os / path格式是什么,都可以从路径中提取文件名

时间:2011-12-05 11:39:50

标签: python

无论操作系统或路径格式是什么,我都可以使用哪个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

20 个答案:

答案 0 :(得分:932)

实际上,有function可以完全返回您想要的内容

print(os.path.basename(your_path))

答案 1 :(得分:599)

在所有情况下使用os.path.splitos.path.basename不会起作用:如果您在Linux上运行脚本并尝试处理经典的Windows样式路径,则会失败。

Windows路径可以使用反斜杠或正斜杠作为路径分隔符。因此,ntpath模块(在Windows上运行时相当于os.path)将适用于所有平台上的所有(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文件名中很少使用反斜杠,但是在编码时请记住这一点,这样就不会产生意外的安全漏洞。

答案 2 :(得分:180)

os.path.split 是你正在寻找的功能

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

>>> print(tail)
a.dat
>>> print(head)
/tmp/d

答案 3 :(得分:36)

在python 3中

>>> from pathlib import Path    
>>> Path("/tmp/d/a.dat").name
'a.dat'

答案 4 :(得分:33)

import os
head, tail = os.path.split(p)
print tail

假设p是输入字符串,tail就是你想要的。

有关详细信息,请参阅python os module docs

答案 5 :(得分:11)

在您的示例中,您还需要从右侧剥离斜线以返回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的路径。

答案 6 :(得分:8)

fname = str("C:\Windows\paint.exe").split('\\')[-1:][0]

这将返回: paint.exe

  

更改有关路径或操作系统的拆分功能的sep值。

答案 7 :(得分:7)

这适用于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']

答案 8 :(得分:7)

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

答案 9 :(得分:5)

我从未见过双背路径,是否存在? 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))

答案 10 :(得分:5)

如果您的文件路径不以“ /”结尾并且目录以“ /”分隔,则使用以下代码。我们知道,路径通常不以“ /”结尾。

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类型将两者组合为一个功能并返回结果。

答案 11 :(得分:4)

如果要自动获取文件名,可以这样做

import glob

for f in glob.glob('/your/path/*'):
    print(os.path.split(f)[-1])

答案 12 :(得分:4)

这是一个仅限正则表达式的解决方案,它似乎适用于任何操作系统上的任何操作系统路径。

不需要其他模块,也不需要预处理:

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\),请将正则表达式更改为:{{1} }。对于“正则表达式挑战”,这会将某种斜杠的积极前瞻性改变为负前瞻性前瞻,导致以斜杠结尾的路径名不返回任何内容路径名中的最后一个子目录。当然,无法保证潜在文件名实际上是指文件,并且需要使用r'[^\\/]+(?![\\/])$'os.path.is_dir()

这将匹配如下:

os.path.is_file()

可以测试正则表达式here

答案 13 :(得分:3)

如果您在一个目录中有许多文件并且想要将这些文件名存储到一个列表中。使用以下代码。

import os as os
import glob as glob
path = 'mypath'
file_list= []
for file in glob.glob(path):
    data_file_list = os.path.basename(file)
    file_list.append(data_file_list)

答案 14 :(得分:3)

Windows分隔符可以是Unix文件名或Windows路径。 Unix分隔符只能存在于Unix路径中。 Unix分隔符的存在表示非Windows路径。

以下将通过OS特定分隔符剥离(剪切尾随分隔符),然后拆分并返回最右边的值。它很难看,但基于上面的假设很简单。如果假设不正确,请更新,我将更新此响应以匹配更准确的条件。

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

答案 15 :(得分:2)

也许只是我的所有解决方案都没有重要的新内容(关于创建临时文件的临时文件:D)

import tempfile
abc = tempfile.NamedTemporaryFile(dir='/tmp/')
abc.name
abc.name.replace("/", " ").split()[-1] 

获取abc.name的值将是这样的字符串:'/tmp/tmpks5oksk7' 因此,我可以使用空格/替换.replace("/", " "),然后调用split()。这将返回一个列表,我得到了 带有[-1]

的列表的最后一个元素

无需导入任何模块。

最好的问候

4k3nd0

答案 16 :(得分:1)

为了完整起见,这里是python 3.2 +的pathlib解决方案:

>>> 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。

答案 17 :(得分:0)

在Python 2和3中,都使用模块pathlib2

"woo"

用法:

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],则路径将被重新连接,因此输出只是输入字符串转换为Unix格式,这对于跨平台比较子路径很有用。

答案 18 :(得分:0)

我个人最喜欢的是:

filename = fullname.split(os.sep)[-1]

答案 19 :(得分:-5)

filename = path[path.rfind('/')+1:]