У меня много файлов xml, которые называются так:

First_ExampleXML_Only_This_Should_Be_Name_20211234567+1234565.xml
Second_ExampleXML_OnlyThisShouldBeName_202156789+55684894.xml
Third_ExampleXML_Only_This_Should_Be_Name1_2021445678+6963696.xml
Fourth_ExampleXML_Only_This_Should_Be_Name2_20214567+696656.xml

Мне нужно создать скрипт, который будет перебирать все файлы и переименовывать их, поэтому от примера осталось только следующее:

Only_This_Should_Be_Name.xml
OnlyThisShouldBeName.xml
Only_This_Should_Be_Name1xml
Only_This_Should_Be_Name2.xml

На данный момент у меня есть что-то вроде этого, но я действительно изо всех сил пытаюсь получить именно то, что мне нужно, думаю, это нужно считать от второго _ до _202, и взять все, что между ними.

fnames = listdir('.')
for fname in fnames:
    # replace .xml with type of file you want this to have impact on
    if fname.endswith('.xml):

Кто-нибудь знает, как лучше всего это сделать?

3
John 22 Сен 2021 в 16:31

3 ответа

Лучший ответ

Вы можете разделить содержимое, разделив все xml-файлы символами подчеркивания и переименовать с первым значением в списке, как показано ниже.

import os

fnames = os.listdir('.')
for fname in fnames:
    # replace .xml with type of file you want this to have impact on
    if fname.endswith('.xml'):
        newName = '_'.join(fname.split("_")[2:-1])
        os.rename(fname, newName+".xml")
    else:
        continue

Здесь вы удаляете значения до и после "_".

1
Sangeerththan Balachandran 22 Сен 2021 в 14:05

Здесь есть две проблемы:

Поиск файлов одного типа в каталоге

В то время как listdir будет работать, вы также можете их использовать глобально:

from pathlib import Path

for fn in Path("/path").glob("*.xml"):
    ....

Переименование файлов

В этом случае ваши файлы называются "file_name_NUMBERS.xml", и мы хотим убрать числа, поэтому мы будем использовать регулярное выражение: Изменить: в данном случае это не лучший способ. Просто разделите и объедините, как в другом ответе

import re
from pathlib import Path
for fn in Path("dir").glob("*.xml"):
    new_name = re.search(r"(.*?)_[0-9]+", fn.stem).group(1)
    fn.rename(fn.with_name(new_name + ".xml"))

Изменить: не знаю, почему я слишком усложнял. Я оставлю решение re там для более сложных случаев, но в этом случае вы можете просто сделать:

new_name = "_".join(fn.stem.split("_")[:-1])

Что намного лучше, поскольку не зависит от точного наименования файлов.

Обратите внимание, что вы можете сделать все это без pathlib, но вы просили лучший способ;)

Наконец, чтобы ответить на неявный вопрос, ничто не мешает вам обернуть все это функцией и передать аргумент glob для разных типов файлов.

1
2e0byo 22 Сен 2021 в 13:52

Я думаю, что регулярное выражение будет здесь самым простым подходом, который в Python может быть реализован с помощью модуля re.

import os
import re

fnames = os.listdir('.')
for fname in fnames:
    result = re.sub(r"^.*?_ExampleXML_(.*?)_[\d+]+\.xml$", r"\1.xml", fname)
    if result != fname:
       os.rename(fname, result) 

Есть несколько стратегий сопоставления с образцом, которые вы можете использовать в зависимости от вашего варианта использования.

Например, вы можете попробовать следующие варианты, в зависимости от того, насколько конкретными / общими вы должны быть:

1
dxdc 22 Сен 2021 в 14:44