Як замінити розширення з імені файлу в Python?


112

Чи є вбудована функція в Python, яка б замінила (або видалила, що завгодно) розширення імені файлу (якщо він має)?

Приклад:

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

У моєму прикладі: /home/user/somefile.txtстав би/home/user/somefile.jpg

Я не знаю, чи це має значення, але мені це потрібно для модуля SCON, про який я пишу. (Тож, можливо, є якась функція SCON, яку я можу використовувати?)

Мені б хотілося чогось чистого . Зробити просту заміну рядків усіх випадків .txtвсередині рядка, очевидно, не є чисто. (Це не вдасться, якщо моє ім'я файлу somefile.txt.txt.txt)



SCons дозволяє потрапляти до бази даних у рядку дій. Чи можете ви опублікувати свої скани певної логіки, яка цього потребує? Це для дії, випромінювач, сканер?
бдбаддог

дещо з цього більше не працює, оскільки шлях повертає PosixPath не рядок: p
shigeta

Відповіді:


146

Спробуйте os.path.splitext, він повинен робити те, що ви хочете.

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

15
@ S.Lott: Повірте чи ні. Але я це зробив. Я завжди так роблю. Можливо, з неправильними умовами.
ereO

@ereOn: Оскільки ваше запитання використовує майже таку ж фразу, я трохи здивований, що ви його не знайшли. Ваше запитання містить 5 слів - підряд - які точно відповідають.
S.Lott

Поставте нове ім’я разом з os.path.join, щоб виглядати чисто.
Tony Veijalainen

4
@Tony Veijalainen: Ви не повинні використовувати os.path.join, тому що це для з'єднання компонентів шляху з роздільним контуром для ОС. Наприклад, print os.path.join(os.path.splitext('/home/user/somefile.txt')[0], '.jpg')повернеться /home/user/somefile/.jpg, що не бажано.
scottclowe

@ S.Lott - 99 людей, які голосували на цю відповідь, досить чітко означають, що ця публікація корисна, не потрібно
ганьбити

92

Розгортаючись на відповідь 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
Real Python добре описав приклади використання модуля pathlib
Стівен Хауелл

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

Дивіться мою відповідь нижче щодо вирішення проблеми з кількома розширеннями.
Майкл Холл

33

Як сказав @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його, щоб отримати ім’я файлу за вирахуванням розширення.


8
Зауважте, що використання rsplitпризведе до різних результатів для файлів, які починаються з крапки і не мають іншого розширення (наприклад, приховані файли в Linux, наприклад .bashrc). os.path.splitextповертає порожнє розширення для них, але з використанням rsplitбуде розглядається все ім'я файлу як розширення.
Флоріан Брюкер

4
Це також дасть несподівані результати для назви файлу/home/john.johnson/somefile
Will Manley

7

Я віддаю перевагу наступному однолінійному підходу за допомогою str.rsplit () :

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

Приклад:

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

2
Це не вдається, якщо деякий файл не має розширення, а користувач - "john.doe".
Marek Jedliński

Хіба не всі вони тоді провалилися б?
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
Я думаю, що підхід pathlib, запропонований JS. набагато простіше.
h0b0

4

Обробка декількох розширень

У випадку, коли у вас є кілька розширень, цей одноклапник використовує pathlibта str.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_suffixume" 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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.