如何在 Python 中替换(或删除)文件名的扩展名?

发布于 2024-09-15 18:54:21 字数 441 浏览 7 评论 0原文

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

示例:

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

在我的示例中: /home/user/somefile.txt 将变为 /home/user/somefile.jpg

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

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

Is there a built-in function in Python that would replace (or remove, whatever) the extension of a filename (if it has one)?

Example:

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

In my example: /home/user/somefile.txt would become /home/user/somefile.jpg

I don't know if it matters, but I need this for a SCons module I'm writing. (So perhaps there is some SCons specific function I can use ?)

I'd like something clean. Doing a simple string replacement of all occurrences of .txt within the string is obviously not clean. (This would fail if my filename is somefile.txt.txt.txt)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

南街九尾狐 2024-09-22 18:54:21

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

import os
print os.path.splitext('/home/user/somefile.txt')[0]+'.jpg'  # /home/user/somefile.jpg
os.path.splitext('/home/user/somefile.txt')  # returns ('/home/user/somefile', '.txt')

Try os.path.splitext it should do what you want.

import os
print os.path.splitext('/home/user/somefile.txt')[0]+'.jpg'  # /home/user/somefile.jpg
os.path.splitext('/home/user/somefile.txt')  # returns ('/home/user/somefile', '.txt')
吲‖鸣 2024-09-22 18:54:21

扩展 AnaPana 的答案,如何使用 pathlib 删除扩展 a> (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.txt    

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

>>> print(filename_replace_ext)
/some/path/somefile.jpg

Expanding on AnaPana's answer, how to remove an extension using 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.txt    

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

>>> print(filename_replace_ext)
/some/path/somefile.jpg
清风夜微凉 2024-09-22 18:54:21

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

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

rsplit 告诉 Python 执行字符串从字符串右侧开始拆分,1 表示最多执行一次拆分(例如 'foo.bar.baz' -> [ 'foo.bar', 'baz' ])。由于 rsplit 始终返回一个非空数组,因此我们可以安全地在其中索引 0 来获取减去扩展名的文件名。

As @jethro said, splitext is the neat way to do it. But in this case, it's pretty easy to split it yourself, since the extension must be the part of the filename coming after the final period:

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

The rsplit tells Python to perform the string splits starting from the right of the string, and the 1 says to perform at most one split (so that e.g. 'foo.bar.baz' -> [ 'foo.bar', 'baz' ]). Since rsplit will always return a non-empty array, we may safely index 0 into it to get the filename minus the extension.

瞳孔里扚悲伤 2024-09-22 18:54:21

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

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

示例:

>>> my_filename = '/home/user/somefile.txt'
>>> my_filename.rsplit('.', 1)
>>> ['/home/user/somefile', 'txt']

I prefer the following one-liner approach using str.rsplit():

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

Example:

>>> my_filename = '/home/user/somefile.txt'
>>> my_filename.rsplit('.', 1)
>>> ['/home/user/somefile', 'txt']
初见你 2024-09-22 18:54:21

处理多个扩展

如果您有多个扩展,使用 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")

Handling multiple extensions

In the case where you have multiple extensions using pathlib and str.replace works a treat:

Remove/strip extensions

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

Replace extensions

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

If you also want a pathlib object output then you can obviously wrap the line in Path()

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

Wrapping it all up in a function

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")
乜一 2024-09-22 18:54:21

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。我还担心这里的一些答案不能处理父目录中的 . 。以下是完成扩展替换的几种方法。

使用路径对象

替换最多一个扩展

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 包,我真的很抱歉。

使用 os.path替换所有

兼容 Python 2.7 的扩展:

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+ 使用 removesuffixos.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')

TLDR:
Best way to replace all extensions, in my opinion, is the following.

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

Longer Answer:
The best way to do this will depend on your version of python and how many extensions you need to handle. That said, I'm surprised nobody has mentioned pathlib's with_name. I'm also concerned that some answers here don't handle a . in the parent directories. Here are several ways to accomplish extension replacement.

Using Path Objects

Replace Up to One Extension

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

Replace Up to Two Extensions

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

Replace All Extensions

Using pathlibs with_name (best solution, in my opinion):

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

Using functools.reduce and pathlib's 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+ Using pathlib and 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'))

Without Using Path Objects (Strings Only)

In general, I think solutions using pathlib are cleaner, but not everybody can do that. If you're still using python 2, I'm sorry. If you don't have the pathlib package for python2, I'm really sorry.

Replace All Extensions

Python 2.7 compatible using 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+ Using removesuffix and os.path (if you have python3.9, why aren't you using pathlib?):

import os
ps = '/path/to.my/file.foo.bar.baz.quz'
print(ps.removesuffix(os.path.splitext(ps)[-1].split('.', 1)[-1]) + 'jpg')
青瓷清茶倾城歌 2024-09-22 18:54:21

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

例如:

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

new_filename = prefix + '.jpg'

print new_filename

Another way to do is to use the str.rpartition(sep) method.

For example:

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

new_filename = prefix + '.jpg'

print new_filename
千里故人稀 2024-09-22 18:54:21

对于 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'

For 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'
无尽的现实 2024-09-22 18:54:21

使用 f 字符串:

>>> from pathlib import Path
>>> p = Path('/some/path/somefile.txt')
>>> p_new = p.parent / f"{p.stem}.jpg"
>>> p_new
WindowsPath('/some/path/somefile.jpg')

Use f-strings:

>>> from pathlib import Path
>>> p = Path('/some/path/somefile.txt')
>>> p_new = p.parent / f"{p.stem}.jpg"
>>> p_new
WindowsPath('/some/path/somefile.jpg')
素食主义者 2024-09-22 18:54:21

最简单的方法:

from pathlib import Path

path = Path("/home/user/somefile.txt")
path_jpg = path.with_suffix('.jpg')

The simplest way to do it:

from pathlib import Path

path = Path("/home/user/somefile.txt")
path_jpg = path.with_suffix('.jpg')
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文