在Python中提取文件名的后缀

在Python中提取文件名的后缀,python,python-3.x,Python,Python 3.x,我正在使用Python从文件名列表创建HTML链接。 文件名的格式如下:song1_lead.pdf、song1_Lyps.pdf。 他们也可以有像song2_这样的名字,加上额外的下划线。但常见的是,它们都将以_someText.pdf结尾 我的目标是只提取someText部分,在最后一个下划线之后,不带.pdf扩展名。所以song1_歌词.pdf的结果是:歌词 我有下面的Python代码实现了我的目标,但看起来我做得很艰难。 有没有更有效的方法 testString='file1\u加上额外

我正在使用Python从文件名列表创建HTML链接。 文件名的格式如下:song1_lead.pdf、song1_Lyps.pdf。 他们也可以有像song2_这样的名字,加上额外的下划线。但常见的是,它们都将以_someText.pdf结尾

我的目标是只提取someText部分,在最后一个下划线之后,不带.pdf扩展名。所以song1_歌词.pdf的结果是:歌词

我有下面的Python代码实现了我的目标,但看起来我做得很艰难。 有没有更有效的方法

testString='file1\u加上额外下划线\u lead.pdf'
#步骤1:使用under_分数的最后一次出现来分隔字符串
HTMLtext=testString.rpartition(“”)
#结果:('file1_加上_额外的_下划线',''.'歌词.pdf')
#步骤2:将后缀和.pdf扩展名分开。
HTMLtext=HTMLtext[2]。r分区('.'))
#结果:('lead','pdf')
#步骤3:使用第一项作为最终结果。
HTMLtext=HTMLtext[0]#结果:领先
我在想,我正在尝试的是用更少的代码行来实现,而不必像现在这样多次设置HTMLtext。

这应该很好:

testString = 'file1_with_extra_underscores_lead.pdf'
testString[testString.rfind('_') + 1:-4]
但是,在这里检查时没有错误。如果字符串中没有“\u1”,则将失败。 你也可以使用正则表达式。这应该不难

基本上我自己不会这样做。最好进行一些异常处理,除非您100%确定不需要进行异常处理。

您可以使用Path from提取最终路径组件,而不带后缀:

from path import Path
Path('file1_with_extra_underscores_lead.pdf').stem.split('_')[-1]
输出:

'lead'
这将适用于“…\u lead.pdf”或“…\u lead.pdf”:


正如@wwii在其评论中所说的,您应该使用专门设计用于将文件名与其扩展名分开的和/或专门设计用于在一个字符处剪切字符串的。使用这些函数有几种方法可以实现您想要的

与@wwii不同,我将首先放弃扩展:

test_string = 'file1_with_extra_underscores_lead.pdf'
filename = os.path.splitext(test_string)[0]
print(filename)  # 'file1_with_extra_underscores_lead'
然后我将使用
split
rsplit
,使用
maxslit
参数或选择结果列表的最后一个(或第二个索引)(根据使用的方法)。以下每一行都是等效的(至少在功能方面):

最好的可能是最后两种解决方案之一,因为它不会进行无用的拆分


为什么这个答案比其他答案好?(至少在我看来)

  • 使用
    pathlib
    是可以的,但是对于将文件名与其扩展名分离,
    os.path.splitext
    可能更有效
  • 使用带有
    rfind
    的切片可以工作,但不能清楚地表达代码意图,因此可读性较差
  • 使用
    endswith('.pdf')
    是可以的,如果您确信您永远不会使用pdf以外的任何东西。如果有一天你使用
    .txt
    ,你将不得不重新编写你的代码
  • 我喜欢regex,但在这种情况下,它与前面讨论的两种解决方案有着相同的警告:没有明确的意图,可读性不强,如果有一天使用其他扩展,您将不得不重新编写它
使用
splitext
清楚地表明您对扩展做了一些事情,并且第一项选择非常明确。这仍然适用于任何其他扩展。
使用rsplit(“”,maxslit=1)并选择最后一个索引也非常有表现力,比任意外观的切片清晰得多。

这是3行代码。我不确定我是否会关心这个tbh,它为您提供了一个在各个阶段捕获异常的机会。关于
if testString.endswith('.pdf'):print(testString.split('.pdf')[0])
*\ukeep=testString.rsplit('.pdf'):print(testString.split('.pdf')[0]);keep,=os.path.splitext(keep)
-仅两行。其中一个答案使用
pathlib
,它将
路径
视为
对象,而不是
字符串
。因此,有许多内置方法可用于访问路径的各个部分。还有,你说得对。修正了。现在这里没有活动的python环境好的,它现在可以工作了,但是您承认如果字符串不是预期的格式,它就会成为一个问题。我不明白解决了什么问题,也不明白OP的动机。但这是可行的。他要求提高效率。据我所知,这应该更有效率。他的版本使用了2个对rpartition的调用和2个对array操作符的调用,以及2个内存操作。我的版本应该更有效。少1个函数调用,少1个数组运算符,不向同一变量写入3次。在几乎每种情况下都不重要,但是。。。嗯,应该是稍微快一点,这很有效,并且可以处理我扔给它的所有文件。从path导入path testFiles=['song1_with_multiple_underlines_Lead.pdf'、'song1_lymps.pdf'、'song2_ChordsF.pdf'、'song2_Lead.pdf']用于测试文件中的fn:HTMLtext=path(fn).stem.split('.[-1]#只获取后缀,而不包含分数或.pdf打印(HTMLtext+“->”+fn)结果:Lead->song1\u带多个下划线\u Lead.pdf歌词->song1\u歌词.pdf ChordsF->song2\u ChordsF.pdf Lead->song2\u Lead.pdf我的代码看起来很乱。无法确定如何使用代码进行注释并将其正确格式化。为了避免拆分整个字符串并创建不必要的列表,可以更改为
str.rpartition('''[-1]
,这比
str.rsplit(''''1][-1]
test_string = 'file1_with_extra_underscores_lead.pdf'
filename = os.path.splitext(test_string)[0]
print(filename)  # 'file1_with_extra_underscores_lead'
filename.split('_')[-1]  # splits at each underscore and selects the last chunk
filename.rsplit('_')[-1]  # same as previous line except it splits from the right of the string
filename.rsplit('_', maxsplit=1)[-1]  # split only one time from the right of the string and selects the last chunk
filename.rsplit('_', maxsplit=1)[1]  # same as previous line except it select the second chunks (which is the last since only one split occured)