@AlexHDreal

Как реализовать копирование файлов с одинаковыми именами под разными именами, а не перезаписывать созданный файл при нахождении одноимённого файла?

PYTHON

Помогите. На диске имеется неизвестное кол-во файлов с одинаковым названием "pic one". Нужно найти их все и сделать копии, но уже с разными последовательными названиями (пример: pic1, pik2, pic3.......) чтобы избежать перезаписи одного и того же файла найденным с аналогичным названием.
#КОД ИЩЕТ ФАЙЛ И КОПИРУЕТ ЕГО В УКАЗАННОЕ МЕСТО

import os

    name = 'pic one.jpg'
    disk = ('C:\\')

    for root, dirs, files in os.walk(disk):

        if name in dirs or name in files:
        print(f'We find {name} in {root}')

        filen1 = (f'{root}' + str('\\') + f'{name}')
        filen2 = 'C:\\Users\\........\\Desktop\\test\\pic.jpg'

        file1 = open(filen1, 'rb')
        file2 = open(filen2, 'wb')

        file2.write(file1.read())

        file1.close()
        file2.close()
        print('COPY COMPLETED')

print ('THE END')
input()
  • Вопрос задан
  • 1394 просмотра
Пригласить эксперта
Ответы на вопрос 1
trapwalker
@trapwalker Куратор тега Python
Программист, энтузиаст
Есть несколько простых правил:

0. Следите за отступами и форматируйте код правильно.
Для питона это самое главное правило. Вы некорректно наставили тегов для оборачивания кода, я вам лишние убрал, но ваши отступы в коде поломаны. К этому нужно относиться внимательно.
Помните, что помимо пробелов бывают табуляции. Табуляция - это один широкий символ, но его ширина нигде не регламентирована, а питон по количеству пустых символов вначале строки понимает её вложенность в коде. Само собой смешение табуляций и пробелов в питоновском коде ведёт к страшной неразберихе и гарантированным ошибкам. Холивару "пробелы против табов" не одна сотня человеко-лет, но есть общее правило, зафиксированное в PEP: используйте 4 пробела в качестве одного отступа. Всегда. Без исключений.

1. Не используйте скобки там, где они не нужны:
disk = ('C:\\')
filen1 = (f'{root}' + str('\\') + f'{name}')

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

1. Не конкатенируйте пути вручную, как вы это делаете здесь:
f'{root}' + str('\\') + f'{name}'
Приведение строки к строке бессмысленно. Могли бы просто написать так: f'{root}\\{name}', но и это плохая идея, потому что нельзя конкатенировать пути вручную. В разных операционных системах используются разные символы-разделители в путях. В питоне для работы с путями есть модули: os.path (древний как навоз мамонта) и pathlib (новый, объектный, очень удобный).

2. Используйте pathlib для работы с путями.
Изучите эту библиотеку. Вы откроете для себя массу полезных вещей.

3. Используйте оператор with при работе с закрываемыми ресурсами.
Ваш код:
file1 = open(filen1, 'rb')
file2 = open(filen2, 'wb')
file2.write(file1.read())
file1.close()
file2.close()

Станет таким:
with open(filen1, 'rb') as file1, open(filen2, 'wb') as file2:
    file2.write(file1.read())

А с использованием pathlib ещё лаконичнее:
directory = Path('path/to/my/dir')
fn1 = directory / 'file1.jpg'
fn2 = directory / 'file2.jpg'
file2.write_bytes(file1.read_bytes())

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

4. Не смешивайте работу с каталогами и с файлами:
if name in dirs or name in files:
В каких-то случаях, возможно, и есть сходства, ведь в файловой системе каталог - это тоже файл. Но вы не сможете его ни прочитать, как таковой ни записать. По логике вашей программы получается, что, если есть каталог с таким именем и расширением, то вы его будете тоже пытаться читать. на этом ваш код и упадёт.
В pathlib, кстати, есть отличный метод rglob, который рекурсивно итерируется по всем путям, соответствующим маске. Сделать это можно относительно любого каталога:
files = Path('c:').rglob('*.jpg')
найдёт все jpeg-картинки на вашем диске c:.
При этом вы получите объект, по которому можно итерироваться циклом или превратить его в список. Элементы такой последовательности будут тоже типа pathlib.Path.

5. Для решения любой задачи разбейте ее на элементарные части и решайте их по отдельности.
В данном случае логично написать отдельную функцию безопасного копирования одного файла. Эта функция должна проверить есть ли целевое имя файла (если нет, то копирует), какого размера там файл (если такого-же до байта, то нужно проверить хеш и отказаться от копирования при совпадении, если другого, то нужно менять целевое имя или путь). С помощью pathlib можно подставлять расширение и быстро получить все файлы по маске в каталоге. Это позволит, например, быстро понять какой самый последний файл с именем вида 'file_name_00023.jpg' по маске 'file_name_*****.jpg', достать его цифровой хвостик, превратить в целое число, прибавить единицу и снова подставить в имя: Path('file_name_{last_index+1:05}.jpg').

6. Подозреваю вы хотите написать безопасную дедупликацию картинок.
  • Прочитайте про хеш-функции и как они могут помочь сказать наверняка одинаковы ли два файла.
  • Прочитайте про символические ссылки. Это как ярлыки, но на уровне файловой системы и с файлами можно работать точно так же как с оригиналами. Такие ссылки позволят не копировать и не дублировать данные, когда требуется лишь как-то альтернативно сгруппировать их по каталогам.
  • Прочитайте про жесткие ссылки. Это выглядит как несколько имён одного файла в произвольных каталогах. Если хоть одно имя останется не удалённым, то и файл на диске будет. Данные хранятся один раз, а лежит файл как бы сразу в нескольких местах и нет никакого приоритета между ними.
  • Подумайте о журналировании. Иногда правильнее вместо реальных операций с файловой системой написать подробный журнал того, что вы хотите сделать в ней, а затем, по окончании опасного длительного процесса сборки этого журнала, можно утвердить и согласовать действия с пользователем, проанализировать список предстоящих операций и выполнить уже их спокойно или отказаться от них.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы