200

Python中是否有一个内置函数可以替换(或删除,无论如何)文件名的扩展名(如果有的话)?

例子:

print replace_extension('/home/user/somefile.txt', '.jpg')

在我的例子中:/home/user/somefile.txt会变成/home/user/somefile.jpg

我不知道这是否重要,但我需要这个用于我正在编写的 SCons 模块。(所以也许我可以使用一些 SCons 特定功能?)

我想要一些干净的东西。对字符串中所有出现的 进行简单的字符串替换.txt显然是不干净的。(如果我的文件名是 ,这将失败somefile.txt.txt.txt

4

8 回答 8

232

尝试os.path.splitext它应该做你想做的事。

import os
print os.path.splitext('/home/user/somefile.txt')[0]+'.jpg'
于 2010-08-23T14:51:09.613 回答
167

扩展 AnaPana 的答案,如何使用pathlib (Python >= 3.4)删除扩展:

>>> from pathlib import Path

>>> filename = Path('/some/path/somefile.txt')

>>> filename_wo_ext = filename.with_suffix('')

>>> filename_replace_ext = filename.with_suffix('.jpg')

>>> print(filename)
/some/path/somefile.ext    

>>> print(filename_wo_ext)
/some/path/somefile

>>> print(filename_replace_ext)
/some/path/somefile.jpg
于 2017-02-17T01:58:10.580 回答
44

正如@jethro 所说,splitext这是一种巧妙的方法。但在这种情况下,自己拆分很容易,因为扩展名必须是最后一个句点之后的文件名部分:

filename = '/home/user/somefile.txt'
print( filename.rsplit( ".", 1 )[ 0 ] )
# '/home/user/somefile'

告诉 Python 从字符串的rsplit右侧开始执行字符串拆分,并且1说最多执行一次拆分(例如'foo.bar.baz'-> [ 'foo.bar', 'baz' ])。由于rsplit总是返回一个非空数组,我们可以安全地索引0它以获得文件名减去扩展名。

于 2010-08-23T14:56:51.933 回答
16

我更喜欢使用str.rsplit()的以下单行方法:

my_filename.rsplit('.', 1)[0] + '.jpg'

例子:

>>> my_filename = '/home/user/somefile.txt'
>>> my_filename.rsplit('.', 1)
>>> ['/home/user/somefile', 'txt']
于 2016-11-18T06:55:59.923 回答
13

处理多个扩展

如果您有多个扩展使用pathlibstr.replace工作:

删除/剥离扩展

>>> from pathlib import Path
>>> p = Path("/path/to/myfile.tar.gz")
>>> extensions = "".join(p.suffixes)

# any python version
>>> str(p).replace(extensions, "")
'/path/to/myfile'

# python>=3.9
>>> str(p).removesuffix(extensions)
'/path/to/myfile'

替换扩展

>>> p = Path("/path/to/myfile.tar.gz")
>>> extensions = "".join(p.suffixes)
>>> new_ext = ".jpg"
>>> str(p).replace(extensions, new_ext)
'/path/to/myfile.jpg'

如果您还想要一个pathlib对象输出,那么您显然可以将该行换成Path()

>>> Path(str(p).replace("".join(p.suffixes), ""))
PosixPath('/path/to/myfile')

将其全部包装在一个函数中

from pathlib import Path
from typing import Union

PathLike = Union[str, Path]


def replace_ext(path: PathLike, new_ext: str = "") -> Path:
    extensions = "".join(Path(path).suffixes)
    return Path(str(p).replace(extensions, new_ext))


p = Path("/path/to/myfile.tar.gz")
new_ext = ".jpg"

assert replace_ext(p, new_ext) == Path("/path/to/myfile.jpg")
assert replace_ext(str(p), new_ext) == Path("/path/to/myfile.jpg")
assert replace_ext(p) == Path("/path/to/myfile")
    
于 2019-06-28T13:33:07.163 回答
6

另一种方法是使用str.rpartition(sep)方法。

例如:

filename = '/home/user/somefile.txt'
(prefix, sep, suffix) = filename.rpartition('.')

new_filename = prefix + '.jpg'

print new_filename
于 2013-12-17T19:33:11.243 回答
6

对于 Python >= 3.4:

from pathlib import Path

filename = '/home/user/somefile.txt'

p = Path(filename)
new_filename = p.parent.joinpath(p.stem + '.jpg') # PosixPath('/home/user/somefile.jpg')
new_filename_str = str(new_filename) # '/home/user/somefile.jpg'
于 2017-02-10T00:36:42.643 回答
6

TLDR: 在我看来,替换所有扩展的最佳方法如下。

import pathlib
p = pathlib.Path('/path/to.my/file.foo.bar.baz.quz')
print(p.with_name(p.name.split('.')[0]).with_suffix('.jpg'))

更长的答案: 执行此操作的最佳方法将取决于您的 python 版本以及您需要处理多少扩展。也就是说,我很惊讶没有人提到 pathlib 的with_name. 我还担心这里的某些答案无法处理.父目录中的 a 。以下是完成扩展替换的几种方法。

使用路径对象

最多更换一个分机

import pathlib
p = pathlib.Path('/path/to.my/file.foo')
print(p.with_suffix('.jpg'))

最多替换两个扩展

import pathlib
p = pathlib.Path('/path/to.my/file.foo.bar')
print(p.with_name(p.stem).with_suffix('.jpg'))

替换所有扩展

使用 pathlibs with_name(我认为最好的解决方案):

import pathlib
p = pathlib.Path('/path/to.my/file.foo.bar.baz.quz')
print(p.with_name(p.name.split('.')[0]).with_suffix('.jpg'))

使用functools.reduce和 pathlib 的with_suffix

import pathlib
import functools
p = pathlib.Path('/path/to.my/file.foo.bar.baz.quz')
print(functools.reduce(lambda v, _: v.with_suffix(''), p.suffixes, p).with_suffix('.jpg'))
print(functools.reduce(lambda v, e: v.with_suffix(e), ['' for _ in p.suffixes] + ['.jpg'], p))

Python 3.9+使用 pathlib 和 str.removesuffix:

import pathlib
p = pathlib.Path('/path/to.my/file.foo.bar.baz.quz')
print(pathlib.Path(str(p).removesuffix(''.join(p.suffixes))).with_suffix('.jpg'))

不使用路径对象(仅限字符串)

一般来说,我认为使用 pathlib 的解决方案更干净,但不是每个人都能做到。如果您仍在使用 python 2,我很抱歉。如果你没有python2的pathlib包,真的很抱歉。

替换所有扩展

Python 2.7 兼容使用os.path

import os
ps = '/path/to.my/file.foo.bar.baz.quz'
print(os.path.join(os.path.dirname(ps), os.path.basename(ps).split('.')[0] + '.jpg'))

Python 3.9+使用removesuffixand os.path(如果你有 python3.9,你为什么不使用pathlib?):

import os
ps = '/path/to.my/file.foo.bar.baz.quz'
print(ps.removesuffix(os.path.splitext(ps)[-1].split('.', 1)[-1]) + 'jpg')
于 2021-02-23T14:54:07.953 回答