Есть несколько простых правил:
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. Подозреваю вы хотите написать безопасную дедупликацию картинок.
- Прочитайте про хеш-функции и как они могут помочь сказать наверняка одинаковы ли два файла.
- Прочитайте про символические ссылки. Это как ярлыки, но на уровне файловой системы и с файлами можно работать точно так же как с оригиналами. Такие ссылки позволят не копировать и не дублировать данные, когда требуется лишь как-то альтернативно сгруппировать их по каталогам.
- Прочитайте про жесткие ссылки. Это выглядит как несколько имён одного файла в произвольных каталогах. Если хоть одно имя останется не удалённым, то и файл на диске будет. Данные хранятся один раз, а лежит файл как бы сразу в нескольких местах и нет никакого приоритета между ними.
- Подумайте о журналировании. Иногда правильнее вместо реальных операций с файловой системой написать подробный журнал того, что вы хотите сделать в ней, а затем, по окончании опасного длительного процесса сборки этого журнала, можно утвердить и согласовать действия с пользователем, проанализировать список предстоящих операций и выполнить уже их спокойно или отказаться от них.