Получить уникальный путь файла с числовым суффиксом в скобках

Вопрос или проблема

Я ищу функцию, которая может обрабатывать случаи, когда путь к входному файлу уже содержит числовой суффикс в скобках. Текущая реализация моей функции get_unique_path увеличивает числовой суффикс на единицу, пока не найдет путь, который не существует. Однако этот подход не работает, когда путь к входному файлу уже содержит числовой суффикс.

Например, если путь к входному файлу example(1).txt, функция неправильно добавит ещё одну пару скобок и число, в результате получится example(1)(2).txt. Вместо этого я хочу, чтобы функция проверяла базовый путь на наличие существующих скобок и увеличивала числовой суффикс соответственно.

Вот моя текущая реализация:

def get_unique_path(file_path: str, extension: str) -> Optional[str]:
    base_path = os.path.splitext(file_path)[0]
    attempt = 1
    while True:
        path = f"{base_path}({attempt + 1}).{extension}"
        
        if not os.path.exists(path):
            return path
        
        attempt += 1

Я хотел бы изменить эту функцию, чтобы обработать случаи, когда путь к входному файлу уже содержит числовой суффикс в скобках. Может кто-нибудь предложить решение?

Очевидный первый шаг — проверить, содержит ли file_path уже число в скобках, и удалить его, если это так. Мы можем использовать re модуль для выполнения этой операции.

Одним из возможных вариантов реализации является:

import re
from pathlib import Path

re_marker = re.compile(r"(?P<prefix>.*)\(\d+\)$")


def get_unique_path(file_path: str | Path) -> str:
    file_path = Path(file_path)
    parent = file_path.parent
    base = file_path.stem
    if mo := re_marker.match(base):
        base = mo.group("prefix")

    count = 1
    while True:
        new_path = parent / f"{base}({count}){file_path.suffix}"
        if not new_path.exists():
            return str(new_path)
        count += 1

Вот несколько простых тестов:

>>> get_unique_path('/tmp/foo')
'/tmp/foo(1)'
>>> # создаём /tmp/foo(1)
>>> open('/tmp/foo(1)', 'w').close()
>>> # проверяем снова
>>> get_unique_path('/tmp/foo')
'/tmp/foo(2)'
>>> # передаем имя файла, которое уже содержит число
>>> get_unique_path('/tmp/foo(1)')
'/tmp/foo(2)'

Чтобы обработать случаи, когда путь к входному файлу уже содержит числовой суффикс в скобках, вы можете использовать регулярные выражения для извлечения базового пути и числового суффикса.

Используйте re.search(r'(.*)\((\d+)\)(\.[^.]+)$', file_path), чтобы сопоставить путь к входному файлу. Затем увеличьте числовой суффикс и создайте новый путь. Если совпадение не найдено, используйте оригинальную логику, чтобы добавить числовой суффикс и увеличивать его, пока не будет найден путь, который не существует.

if match:
    base_path = match.group(1)
    count = int(match.group(2))
    file_extension = match.group(3)

    ...
else:
    ...

Ответ или решение

Для решения проблемы уникальных путей файлов с числовыми суффиксами в скобках мы можем использовать регулярные выражения для извлечения базы пути и числового суффикса. Ваша задача заключается в том, чтобы обрабатывать файлы, которые могут уже содержать такие суффиксы, и правильно увеличивать их.

Ниже представлена модификация вашей функции get_unique_path, которая реализует описанное решение. Мы используем модуль re для поиска числовых суффиксов и инкрементирования их значения.

import re
from pathlib import Path

def get_unique_path(file_path: str | Path) -> str:
    file_path = Path(file_path)
    parent = file_path.parent
    base = file_path.stem
    suffix = file_path.suffix

    # Регулярное выражение для поиска базовой строки и числового суффикса
    match = re.search(r'^(.*)\((\d+)\)$', base)

    if match:
        # Если найдено совпадение, присваиваем новую базу и увеличиваем счётчик
        base = match.group(1)
        count = int(match.group(2))
    else:
        # Если совпадение не найдено, начинаем с первого числа
        count = 0

    while True:
        count += 1
        new_path = parent / f"{base}({count}){suffix}"
        if not new_path.exists():
            return str(new_path)

# Примеры тестов:
# Значения путей предполагают, что папка /tmp существует
print(get_unique_path('/tmp/foo'))      # Выводит: '/tmp/foo(1)'
# Создадим файл для тестирования
open('/tmp/foo(1)', 'w').close()
print(get_unique_path('/tmp/foo'))      # Выводит: '/tmp/foo(2)'
print(get_unique_path('/tmp/foo(1)'))   # Выводит: '/tmp/foo(2)'

Объяснение работы функции:

  1. Импорт библиотек: Импортируем библиотеку re для работы с регулярными выражениями и Path из pathlib для удобного взаимодействия с путями.

  2. Определение функции: Мы определяем функцию get_unique_path, которая принимает строку или объект Path.

  3. Извлечение базового имени и суффикса: Сначала мы получаем родительскую директорию, базовую имя файла (stem) и его расширение (suffix).

  4. Проверка на числовой суффикс: Используя регулярное выражение r'^(.*)\((\d+)\)$', мы пытаемся извлечь базу и числовой суффикс. Если совпадение найдено, мы обновляем базу и начинаем с найденного числа. В противном случае, мы начинаем с 0.

  5. Цикл для поиска уникального пути: В бесконечном цикле мы увеличиваем значение count, создаем новый путь и проверяем, существует ли файл. Если не существует, мы возвращаем путь.

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

Оцените материал
Добавить комментарий

Капча загружается...