如何在Python中从文件名替换(或剥离)扩展名?

问题:如何在Python中从文件名替换(或剥离)扩展名?

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)


回答 0

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

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

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

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

回答 1

扩展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

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.ext    

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

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

回答 2

就像@jethro所说的那样,splitext是一种很好的方法。但是在这种情况下,您可以很容易地自己拆分它,因为扩展名必须是最后一个句点之后的文件名的一部分:

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

rsplit告诉Python从字符串的右边开始执行字符串分割,而告诉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.


回答 3

我更喜欢以下使用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']

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

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'

回答 5

处理多个扩展

如果您有多个扩展名,则此单行代码使用pathlibstr.replace有效对待:

删除/扩展扩展名

>>> from pathlib import Path
>>> p = Path("/path/to/myfile.tar.gz")
>>> str(p).replace("".join(p.suffixes), "")
'/path/to/myfile'

替换扩展名

>>> p = Path("/path/to/myfile.tar.gz")
>>> new_ext = ".jpg"
>>> str(p).replace("".join(p.suffixes), 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 this one-liner using pathlib and str.replace works a treat:

Remove/strip extensions

>>> from pathlib import Path
>>> p = Path("/path/to/myfile.tar.gz")
>>> str(p).replace("".join(p.suffixes), "")
'/path/to/myfile'

Replace extensions

>>> p = Path("/path/to/myfile.tar.gz")
>>> new_ext = ".jpg"
>>> str(p).replace("".join(p.suffixes), 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')

回答 6

另一种方法是使用该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