简体   繁体   English

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

[英]How can I replace (or strip) an extension from a filename in Python?

Is there a built-in function in Python that would replace (or remove, whatever) the extension of a filename (if it has one)? Python 中是否有一个内置函数可以替换(或删除,无论如何)文件名的扩展名(如果有的话)?

Example:例子:

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

In my example: /home/user/somefile.txt would become /home/user/somefile.jpg在我的例子中: /home/user/somefile.txt将变成/home/user/somefile.jpg

I don't know if it matters, but I need this for a SCons module I'm writing.我不知道这是否重要,但是我正在编写的 SCons 模块需要这个。 (So perhaps there is some SCons specific function I can use ?) (所以也许我可以使用一些 SCons 特定功能?)

I'd like something clean .我想要干净的东西。 Doing a simple string replacement of all occurrences of .txt within the string is obviously not clean.对字符串中所有出现的.txt进行简单的字符串替换显然是不干净的。 (This would fail if my filename is somefile.txt.txt.txt ) (如果我的文件名是somefile.txt.txt.txt这将失败)

Try os.path.splitext it should do what you want.试试os.path.splitext它应该做你想做的。

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

Expanding on AnaPana's answer, how to remove an extension using pathlib (Python >= 3.4):扩展 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

As @jethro said, splitext is the neat way to do it.正如@jethro 所说, splitext是一种巧妙的方法。 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 eg 'foo.bar.baz' -> [ 'foo.bar', 'baz' ] ). rsplit告诉 Python 从字符串的右侧开始执行字符串拆分,而1表示最多执行一次拆分(例如'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.由于rsplit将始终返回一个非空数组,我们可以安全地将0索引到其中以获取文件名减去扩展名。

Handling multiple extensions处理多个扩展

In the case where you have multiple extensions using pathlib and str.replace works a treat:在你有使用多个扩展名的情况下pathlibstr.replace作品一种享受:

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()如果你还想要一个pathlib对象输出,那么你显然可以在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')
    

I prefer the following one-liner approach using str.rsplit() :我更喜欢使用str.rsplit()的以下单行方法:

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

Example:例子:

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

Another way to do is to use the str.rpartition(sep) method.另一种方法是使用str.rpartition(sep)方法。

For example:例如:

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

new_filename = prefix + '.jpg'

print new_filename

For Python >= 3.4:对于 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'

TLDR TLDR

Best way to replace all extensions, in my opinion:在我看来,替换所有扩展的最佳方法:

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

Longer Answer: The best way to do this will depend on your version of python and how many extensions you need to handle.更长的答案:执行此操作的最佳方法将取决于您的 Python 版本以及您需要处理的扩展数量。 That said, I'm surprised nobody has mentioned pathlib's with_name .也就是说,我很惊讶没有人提到 pathlib 的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):使用 pathlibs with_name (我认为最好的解决方案):

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

Using functools.reduce and pathlib's with_suffix :使用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+ Using pathlib and str.removesuffix: 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'))

Without Using Path Objects (Strings Only)不使用路径对象(仅限字符串)

In general, I think solutions using pathlib are cleaner, but not everybody can do that.总的来说,我认为使用 pathlib 的解决方案更简洁,但并不是每个人都能做到这一点。 If you're still using python 2, I'm sorry.如果你还在使用 python 2,对不起。 If you don't have the pathlib package for python2, I'm really sorry.如果你没有python2的pathlib包,我真的很抱歉。

Replace All Extensions替换所有扩展

Python 2.7 compatible using os.pathlib :使用os.pathlib与 Python 2.7 兼容:

import os
ps = '/path/to.my/file.foo.bar.baz.quz'
print(ps.removesuffix(os.path.splitext(ps)[-1].split('.', 1)[-1]) + 'jpg')

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM