Мы до сих пор пользуемся винрарным портативным фотоаппаратом типа "мыльница" Canon SX280HS, который пока что рука не поднимается отправить в утиль - ведь основная функция до сих пор работает :)
В последние дни ушедшего года счётчик фотографий в очередной раз преодолел рубеж 10 тыс. снимков, что в таких фотоаппаратах Canon сбрасывает нумерацию, т.е. после снимка IMG_9999.jpg
идёт IMG_0001.jpg
, и последовательность нарушается, если фотографии оказываются в одном каталоге. Обычно я добавляю дату съёмки в начало имени файла (чтоб получить уникальные имена - возможно, пригодится в будущем), но это не особо помогает, если счётчик обнулился в течение дня.
Соответственно, возникает задача исправить имена так, чтобы последовательность соответствовала заснятым событиям. Проще всего подправить имена вида IMG_0001.jpg
, заменив первый нуль на A
, т.е. в моём случае имена вида 2023.12.24_IMG_0001.jpg
, 2023.12.24_IMG_0010.jpg
, ... преобразуются в 2023.12.24_IMG_A001.jpg
, 2023.12.24_IMG_A010.jpg
, ...
Вручную такую замену делать неинтересно, особенно если файлов много, а писать свой скрипт лень, поэтому я решил прибегнуть к помощи AI-подобных бесплатных сервисов, о чём и пойдёт речь в данной заметке.
Для чистоты эксперимента всем сервисам задание будет сформулировано одинаковым образом - в текстовом виде на английском:
write a Python program to rename files with names like 2023.12.24_IMG_0001.jpg, 2023.12.24_IMG_0010.jpg, ... to 2023.12.24_IMG_A001.jpg, 2023.12.24_IMG_A010.jpg, ...
Copilot от Microsoft
Первым я решил опробовать Copilot от Microsoft, который бесплатно доступен всем желающим, - https://copilot.microsoft.com/.
На запрос сервис бодро выдал якобы рабочий код:
import os
def rename_files(directory, prefix):
for filename in os.listdir(directory):
if filename.startswith(prefix):
# Extract the numeric part from the filename
numeric_part = filename[len(prefix):].split(".")[0]
try:
numeric_value = int(numeric_part)
new_filename = f"{prefix}_A{numeric_value:03d}.jpg"
os.rename(os.path.join(directory, filename), os.path.join(directory, new_filename))
print(f"Renamed {filename} to {new_filename}")
except ValueError:
print(f"Skipping {filename} (not a valid numeric filename)")
# Example usage:
directory_path = "." # CHANGED: renaming files in the current directory
prefix_to_rename = "2023.12.24_IMG"
rename_files(directory_path, prefix_to_rename)
Нетрудно убедиться, что этот код требуемую замену не выполняет, а только выдаёт сообщения вида:
... Skipping 2023.12.24_IMG_0089.jpg (not a valid numeric filename) Skipping 2023.12.24_IMG_0090.jpg (not a valid numeric filename) Skipping 2023.12.24_IMG_0091.jpg (not a valid numeric filename) Skipping 2023.12.24_IMG_0092.jpg (not a valid numeric filename) Skipping 2023.12.24_IMG_0093.jpg (not a valid numeric filename) Skipping 2023.12.24_IMG_0094.jpg (not a valid numeric filename) Skipping 2023.12.24_IMG_0095.jpg (not a valid numeric filename)
Если сообщить сервису, что программа нерабочая, то он охотно признаёт свою ошибку и выдаёт ещё один вариант, который в точности повторяет прыдущий и такой же нерабочий.
Впрочем, код достаточно простой и несложно увидеть, где AI накосячил, - всего два места надо поправить:
import os
def rename_files(directory, prefix):
for filename in os.listdir(directory):
if filename.startswith(prefix):
# Extract the numeric part from the filename
numeric_part = filename[len(prefix):].split(".")[0]
try:
numeric_value = int(numeric_part)
new_filename = f"{prefix}A{numeric_value:03d}.jpg" # FIX2
os.rename(os.path.join(directory, filename), os.path.join(directory, new_filename))
print(f"Renamed {filename} to {new_filename}")
except ValueError:
print(f"Skipping {filename} (not a valid numeric filename)")
# Example usage:
directory_path = "." # CHANGED: renaming files in the current directory
prefix_to_rename = "2023.12.24_IMG_" # FIX1
rename_files(directory_path, prefix_to_rename)
После этого замена работает так, как требуется.
GPT-4 от yeschat.ai
Бесплатного доступа к GPT-4 я пока что не нашёл, поэтому воспользовался сервисом www.yeschat.ai.
Ответ:
import os
def rename_files(directory):
# Loop through all the files in the specified directory
for filename in os.listdir(directory):
# Check if the file name matches the desired pattern
if filename.startswith("2023.12.24_IMG_") and filename.endswith(".jpg"):
# Extract the number part from the file name
number_part = filename.split('_')[2].split('.')[0]
# Create the new file name by replacing the number part
new_filename = filename.replace(number_part, 'A' + number_part.lstrip('0'))
# Rename the file
os.rename(os.path.join(directory, filename), os.path.join(directory, new_filename))
print(f"Renamed '{filename}' to '{new_filename}'")
rename_files('.') # CHANGED: replacing in the current directory
В отличие от предыдущего варианта, в функцию передаётся каталог, но не префикс.
Замену он выполняет неправильно - в результате образуются файлы с именами 2023.12.24_IMG_A1.jpg, 2023.12.24_IMG_A10.jpg, ...
Если ассистенту сообщить о проблеме, то он делает вид, что понимает свою ошибку:
> The code doesn't work as expected - after renaming I get files with names like 2023.12.24_IMG_A1.jpg, 2023.12.24_IMG_A10.jpg,... , but I need 2023.12.24_IMG_A0001.jpg, 2023.12.24_IMG_A0010.jpg,...
>> I understand now. You need the renamed files to maintain their zero padding after the addition of the 'A' character. To achieve this, you can modify the script to add the 'A' and then reapply the zero padding to the number.
В итоге скрипт становится посложнее:
import os
def rename_files(directory):
# Loop through all the files in the specified directory
for filename in os.listdir(directory):
# Check if the file name matches the desired pattern
if filename.startswith("2023.12.24_IMG_") and filename.endswith(".jpg"):
# Extract the number part from the file name
number_part = filename.split('_')[2].split('.')[0]
# Remove leading zeros, add 'A', and then reapply zero padding
new_number_part = 'A' + number_part.lstrip('0').rjust(4, '0')
# Create the new file name by replacing the number part
new_filename = filename.replace(number_part, new_number_part)
# Rename the file
os.rename(os.path.join(directory, filename), os.path.join(directory, new_filename))
print(f"Renamed '{filename}' to '{new_filename}'")
rename_files('.') # CHANGED: renaming in the current directory
Но результат переименования тоже неверный - получаются файлы с именами вида 2023.12.24_IMG_A0001.jpg
, 2023.12.24_IMG_A0010.jpg
, ... (лишний нуль после A
).
Хотя достаточно было исправить исходную версию в одном месте:
import os
def rename_files(directory):
# Loop through all the files in the specified directory
for filename in os.listdir(directory):
# Check if the file name matches the desired pattern
if filename.startswith("2023.12.24_IMG_") and filename.endswith(".jpg"):
# Extract the number part from the file name
number_part = filename.split('_')[2].split('.')[0]
# Create the new file name by replacing the number part
new_filename = filename.replace(number_part, 'A' + number_part[1:]) # FIX
# Rename the file
os.rename(os.path.join(directory, filename), os.path.join(directory, new_filename))
print(f"Renamed '{filename}' to '{new_filename}'")
rename_files('.') # CHANGED: renaming in the current directory
Claude 2.1 от yeschat.ai
Альтернативная LLM от того же сервиса www.yeschat.ai.
Ответ:
import os
import re
date_pattern = r"(\d{4}\.\d{2}\.\d{2})_IMG_\d{4}"
for filename in os.listdir("."):
if re.match(date_pattern, filename):
date_part = re.match(date_pattern, filename).group(1)
idx_part = filename.split("_IMG_")[1].split(".")[0]
new_idx_part = ""
for c in idx_part:
new_idx_part += chr(ord('A') + int(c) - 1)
new_filename = f"{date_part}_IMG_{new_idx_part}.jpg"
print(f"Renaming {filename} to {new_filename}")
os.rename(filename, new_filename)
Тут сразу обращает на себя внимание использоваение regexp'ов, код выглядит замороченным (в стиле "лапша 80-го уровня"), при этом он совершенно нерабочий - происходит замена без учёта префикса, в результате образуются имена вида 2023.12.24_IMG_@@@A.jpg
, 2023.12.24_IMG_@@@B.jpg
, ...
Незачот!
CodeLlama-34b-Instruct от together.ai (дополнение от 15.01.2024)
Open-source LLM на условно-бесплатном сервисе, которую можно (при необходимости) запустить и на своём оборудовании.
Ответ:
import os
dir_path = "." # CHANGED: renaming in the current directory
for filename in os.listdir(dir_path):
if filename.startswith("2023.12.24_IMG_"):
old_filepath = os.path.join(dir_path, filename)
new_filename = filename.replace("IMG_", "IMG_A")
new_filename = new_filename.replace(".jpg", "")
new_filename = new_filename.zfill(4) + ".jpg"
new_filepath = os.path.join(dir_path, new_filename)
os.rename(old_filepath, new_filepath)
import os
dir_path = "." # CHANGED: renaming in the current directory
for filename in os.listdir(dir_path):
if filename.startswith("2023.12.24_IMG_"):
old_filepath = os.path.join(dir_path, filename)
new_filename = filename.replace("IMG_0", "IMG_A")
new_filepath = os.path.join(dir_path, new_filename)
os.rename(old_filepath, new_filepath)
GPT-3.5 от OpenAI (дополнение от 16.01.2024)
import os
def rename_files(directory):
# Get a list of all files in the directory
files = os.listdir(directory)
for file_name in files:
# Check if the file is a JPEG file with the specified naming pattern
if file_name.endswith('.jpg') and file_name.startswith('2023.12.24_IMG_'):
# Extract the numeric part of the file name
numeric_part = file_name.split('_')[-1].split('.')[0]
# Pad the numeric part with leading zeros to ensure correct sorting
padded_numeric_part = numeric_part.zfill(4)
# Create the new file name
new_file_name = f'2023.12.24_IMG_A{padded_numeric_part}.jpg'
# Build the full path of the file
old_file_path = os.path.join(directory, file_name)
new_file_path = os.path.join(directory, new_file_name)
# Rename the file
os.rename(old_file_path, new_file_path)
print(f'Renamed: {file_name} -> {new_file_name}')
if __name__ == "__main__":
target_directory = '.' # CHANGED: renaming in the current directory
# Call the function to rename files
rename_files(target_directory)
zfill(4)
на zfill(3)
, что в целом является верным, однако ИИ не понимает, что numeric_part
- строка, в которой сохранились ведущие нули, и zfill()
тут не поможет.import os
def rename_files(directory):
# Get a list of all files in the directory
files = os.listdir(directory)
for file_name in files:
# Check if the file is a JPEG file with the specified naming pattern
if file_name.endswith('.jpg') and file_name.startswith('2023.12.24_IMG_'):
# Extract the numeric part of the file name
numeric_part = int(file_name.split('_')[-1].split('.')[0]) # FIX1
# Pad the numeric part with leading zeros to ensure correct sorting
padded_numeric_part = str(numeric_part).zfill(3) # FIX2
# Create the new file name
new_file_name = f'2023.12.24_IMG_A{padded_numeric_part}.jpg'
# Build the full path of the file
old_file_path = os.path.join(directory, file_name)
new_file_path = os.path.join(directory, new_file_name)
# Rename the file
os.rename(old_file_path, new_file_path)
print(f'Renamed: {file_name} -> {new_file_name}')
if __name__ == "__main__":
target_directory = '.' # CHANGED: renaming in the current directory
# Call the function to rename files
rename_files(target_directory)
Комментариев нет:
Отправить комментарий