Pythonでファイル名から拡張子を置き換える(または取り除く)方法は?


112

(もしあれば)ファイル名の拡張子を置き換える(または何でも削除する)Pythonの組み込み関数はありますか?

例:

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

私の例では:/home/user/somefile.txtなります/home/user/somefile.jpg

それが重要かどうかはわかりませんが、私が書いているSConsモジュールにはこれが必要です。(おそらく、私が使用できるいくつかのSCons固有の関数があるでしょう?)

きれいなものをお願いします。文字列.txt内のすべての出現を単純な文字列置換を行うことは、明らかにクリーンではありません。(私のファイル名がの場合、これは失敗しますsomefile.txt.txt.txt



SConsは、アクション文字列でファイルベースを取得できます。これを必要とするscons固有のロジックを投稿できますか?これはアクション、エミッター、スキャナー用ですか?
bdbaddog 2015年

パスが文字列ではなくPosixPathを返すため、この一部は機能しなくなったようです:p
shigeta

回答:


146

os.path.splitextを試してみてください。必要な処理が行われるはずです。

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

15
@ S.Lott:私を信じるかどうか。しかし、私はやりました。いつもしています。おそらく間違った条件で。
ereOn 2010

@ereOn:あなたの質問はほぼ同じ言い回しを使用しているので、あなたがそれを見つけられなかったことに少し驚いています。あなたの質問には、正確に一致する5つの単語が続けて含まれています。
S.Lott

見栄えを良くするために、os.path.joinと一緒に新しい名前を入れるだけです。
Tony Veijalainen、2010

4
@Tony Veijalainen:OS固有のパス区切り文字を使用してパスコンポーネントを結合するためのものであるため、os.path.joinを使用しないでください。たとえば、print os.path.join(os.path.splitext('/home/user/somefile.txt')[0], '.jpg')はを返しますが/home/user/somefile/.jpg、これは望ましくありません。
scottclowe

S.Lott @ -アップ-投票99人、この答えはかなりはっきりと、このポストは便利です恥すべて大文字の必要性を意味しない
JeffThompson

91

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

1
実際のPythonには、pathlibモジュールの使用例の優れた記事があります:realpython.com/python-pathlib
Steven C. Howell

2
この答えは私の典型的なアプローチですが、複数のファイル拡張子があると失敗するようです。たとえば、pth = Path('data/foo.tar.gz'); print(pth.with_suffix('.jpg'))が出力されます'data/foo.tar.jpg'。私はあなたができると思いますがpth.with_suffix('').with_suffix('.jpg')、それは不格好であり、ファイル拡張子の.with_suffix('')任意の数のドットを処理するために、任意に長い呼び出しのチェーンを追加する必要があり.ます(確かに、2以上はエキゾチックなエッジケースです)。
電話

@tel whileループを使用してそれを解決できます:pth = Path('data/foo.tar.gz'); while pth != pth.with_suffix(''): pth = pth.with_suffix(''); pth = pth.with_suffix('.jpg')
デリック

複数の拡張機能の問題の解決策については、以下の私の回答を参照しください。
マイケルホール

33

@jethroが言ったsplitextように、それを行うためのきちんとした方法です。しかし、この場合、拡張子は最後のピリオドの後に来るファイル名の一部でなければならないので、自分で分割するのはかなり簡単です。

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

rsplit文字列の右から始まる文字列の分割を実行するためのPythonを伝え、1多くても1つの分割で実行するように言います(そのため例えば'foo.bar.baz'- > [ 'foo.bar', 'baz' ])。rsplitは常に空でない配列を返すので、インデックス0を付けてファイル名から拡張子を除いたものを安全に取得できます。


8
を使用rsplitすると、ドットで始まり、他の拡張子がないファイル(Linuxの隠しファイルなど.bashrc)の結果が異なることに注意してください。os.path.splitextこれらは空の拡張子を返しますが、を使用rsplitするとファイル名全体が拡張子として扱われます。
Florian Brucker、2012年

4
これにより、ファイル名に予期しない結果が発生します/home/john.johnson/somefile
Will Manley

7

私はstr.rsplit()を使用した次の1行のアプローチを好みます。

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

例:

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

2
somefileに拡張子がなく、ユーザーが「john.doe」の場合、これは失敗します。
MarekJedliński17年

それなら彼ら全員が失敗するのではないでしょうか?
eatmeimadanish

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'

1
JSによって提案されたpathlibアプローチだと思います。はるかに簡単です。
h0b0 2017

4

複数の拡張の処理

複数の拡張機能がある場合は、このワンライナーを使用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')

pathlibにはこのためのショートカットがあります。Path()。with_suffix( "")は拡張子を削除し、Path.with_suffix( "。txt")はそれを置き換えます。
リーバイ

正しい。ただし、最初の拡張子のみが削除されます。したがって、上記の例では、「のwith_suffix代わりにreplace」を使用 すると、「私の回答」の.gz代わりに.tar.gz「削除」のみが「一般的」であることが意図されていましたが、単一の拡張子のみを期待する場合はwith_suffix、よりクリーンなソリューションになります。
マイケルホール

3

別の方法は、str.rpartition(sep)メソッドを使用することです。

例えば:

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

new_filename = prefix + '.jpg'

print new_filename
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.