Заполнение пропусков в нумерации файлов

Задача из книги Эл Свейгарта.

Напишите программу которая ищет в папке все файлы с именами, содержащими заданный префикс, такими как spam001. txt, spam002.txt и т.д., и обнаруживает любые пропуски в нумерации файлов (например, имеются файлы spam001.txt и spam003. txt, но отсутствует файл spam002.txt). Программа должна изменять имена файлов с большими номерами таким образом, чтобы ликвидировать имеющиеся пропуски.

import os
import re

dir = 'Моя директория'
files = []
for i in os.listdir(dir):
    if re.match(r'^spam\d{3}.txt$', i): # ищет файлы 001.txt итд
        files.append(i)
files.sort()

if str(files[-1][6]) != len(files):
    for num, file in enumerate(files, start=1):
        os.rename(f'{dir}/{file}', f'{dir}/spam00{num}.txt')
        print(num, file)

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


Ответы (3 шт):

Автор решения: Zhihar

spam00{num}

т.е. вы не предполагаете, что файлов может быть больше 10? :)

Ну решите задачу в лоб

  1. найти все файлы
  2. отсортировать названия файлов

тут можно сделать так - выделить из файла числа и отсортировать имена файлов по числам (так более правильно будет)

  1. переименовать в цикле ВСЕ файлы

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

  1. сформировать новое имя в котором число будет трехсимвольным (посмотрите формат формирования строки)

P.S.

основная мысль - найти все файлы и переименовать все файлы

→ Ссылка
Автор решения: Nansy Bo

Тоже прохожу сейчас эту книгу. Мое решение довольно громоздкое. Уверена можно сократить. Но делает вроде все что хочет от нас книга.

import os, shutil, re

our_path = r'C:\Users\admin\Desktop\papka' 
number_of_file = 1 # Задаю стартовую цифру для файла, этакий счетчик
for file in os.listdir(our_path):
    pattern_number = re.compile(r'(\d{1,})\.txt') # Создаю обьект класса 
    mo = re.findall(pattern_number,file) 
    if len(mo) == 0:
        continue # Если файл в нашей папке не содержит подходящего названия мы продолжаем поиск
    else: # В ином случаем сравниваем номер текущего файла с номером который записали ранее как стартовый(счетчик)
        number_of_current_file = mo[0] 
        if int(number_of_current_file) == number_of_file:
            number_of_file += 1 # Если номер сходится то увеличиваем счетчик на 1
        else: # Если не сходится
            if number_of_file < 10: # Переписываю название итерируемого файла согласно цифре счетчика
                new_file_name = os.path.join(our_path, f'spam00{number_of_file}.txt')
                shutil.move((os.path.join(our_path, file)), os.path.join(our_path, new_file_name))
                number_of_file += 1 #Добавляю к счетчику 1
            elif 9 < number_of_file < 100: # Тоже самое в случае если цифра двухзначная
                new_file_name = os.path.join(our_path, f'spam0{number_of_file}.txt')
                shutil.move((os.path.join(our_path, file)), os.path.join(our_path, new_file_name))
                number_of_file += 1 #Добавляю к счетчику 1
            else: # Тоже самое в случае если цифра больше чем двухзначная
                new_file_name = os.path.join(our_path, f'spam{number_of_file}.txt')
                shutil.move((os.path.join(our_path, file)), os.path.join(our_path, new_file_name))
                number_of_file += 1 #Добавляю к счетчику 1
→ Ссылка
Автор решения: Сека Наз
import os
import re

# Установка текущего рабочего каталога
os.chdir("C:\\Users\\SAS\\Desktop\\python\\BookPython\\prefix")

# Созадем регулярное выражение которое соответсвует именам файлов spam001.txt
regex = re.compile(r'^(.*?)(\d{3})(.*?)$')

# находим файлы подходящем формате в рабочем каталоге
target_file = [target for target in os.listdir('.') if regex.search(target)]

# Организация цикла по ранее найднем файлам 
for id, file in enumerate(target_file):
    target = regex.search(file) 
    before_part = target.group(1)  # любые символы до формат 001
    number_part = target.group(2)  # формат 001
    after_part = target.group(3)   # любые символы после формат 001
    if int(number_part) != id + 1: # отсеиваем файлы с совподающей нумерацией
        new_name = f"{before_part}{(id+1):0{3}}{after_part}" # новое имя файла
        os.rename(file, new_name) # переимновываем файл 
→ Ссылка