Почему файлы удаляются, когда я переименовываю их с помощью этого скрипта Python?

Я создал эту программу, чтобы переименовать все мои случайные имена обоев в wallpaper1, wallpaper2 и так далее, используя этот код:

import os
path = os.chdir("/home/samipkarki/Pictures/Wallpapers")
value = 1
for file in os.listdir("path"):
    new_filename = f'wallpaper{value}.jpg'
    os.rename(file, new_filename)
    value += 1

Но каждый раз, когда я запускаю код, половинные файлы переименовываются, другие удаляются навсегда.


person Community    schedule 22.06.2020    source источник
comment
Если вы переименовываете его во что-то, что уже существует, он переопределит старый файл. Может быть, это так?   -  person jpnadas    schedule 22.06.2020
comment
Да, я думаю, если вы запустите этот код более одного раза, может произойти что-то плохое.   -  person quamrana    schedule 22.06.2020
comment
@quamrana вы правы, но почему это происходит и каково решение, пожалуйста, помогите   -  person    schedule 22.06.2020
comment
А ответы ниже? Кажется, они предлагают некоторые положительные предложения.   -  person quamrana    schedule 22.06.2020


Ответы (4)


Лучше всего сохранять переименованные файлы в отдельную папку, а для номеров можно использовать enumerate():

import os
path = os.chdir("/home/samipkarki/Pictures/Wallpapers")
for n,file in enumerate(os.listdir("path")):
    new_filename = f'wallpaper{n+1}.jpg'
    os.rename(file, "/home/samipkarki/Pictures/Wallpapers2/"+new_filename) # Put it in another folder

Убедитесь, что у вас есть еще одна папка с именем Wallpapers2 в папке «Изображения».

person Ann Zen    schedule 22.06.2020

(Здесь предлагается небольшое изменение, но в качестве ответа, потому что трудно однозначно показать это через комментарии.)

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

import os
path = os.chdir("/home/samipkarki/Pictures/Wallpapers")
value = 1
for file in os.listdir("path"):
    new_filename = f'wallpaper{value}.jpg'
    while os.path.exists(new_filename):
        value += 1
        new_filename = f'wallpaper{value}.jpg'
    os.rename(file, new_filename)
    value += 1
person alani    schedule 22.06.2020
comment
спасибо за ваше предложение, это действительно помогло мне узнать новые вещи и понять правильный код, но единственная проблема, с которой я столкнулся с вашим кодом, заключалась в том, что если я запустил его один раз, он переименовал бы его, но после наибольшего значения предыдущего выполнения, и если тогда если бы я запустил снова, это дало бы мне ожидаемый результат. Итак, я немного изменил код, и теперь он работает отлично. - person ; 24.06.2020

Это деталь, которая немного зависит от платформы. Если бы вы использовали Windows, вы бы получили исключение FileExistsError, но не в Unix.

Вот что говорится в документации:

Переименуйте файл или каталог src в dst. Если dst существует, операция завершится ошибкой с подклассом OSError в ряде случаев:

В Windows, если dst существует, всегда возникает FileExistsError.

В Unix, если src является файлом, а dst — каталогом или наоборот, соответственно будет вызвано сообщение об ошибке IsADirectoryError или NotADirectoryError. Если оба являются каталогами и dst пуст, dst будет заменен молча. Если dst является непустым каталогом, возникает ошибка OSError. Если оба являются файлами, dst будет заменен автоматически, если у пользователя есть разрешение. Операция может завершиться ошибкой в ​​некоторых разновидностях Unix, если src и dst находятся в разных файловых системах. В случае успеха переименование будет атомарной операцией (это требование POSIX).

Поэтому вам нужно выполнить ручную проверку, существует ли файл, и, если он существует, каким-то образом обработать его.

Одна вещь, которая, вероятно, не повлияет на вашу программу, заключается в том, что проверка этой формы (из ответа аланиви):

while os.path.exists(new_filename):
    value += 1
    new_filename = f'wallpaper{value}.jpg'
os.rename(file, new_filename)

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

Комбинация подхода аланиви и это может выглядеть так:

while True:
    value += 1
    new_filename = f'wallpaper{value}.jpg'

    try:
        os.open(new_filename, os.O_CREAT | os.O_EXCL)
        break
    except FileExistsError:
        pass

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

person klutt    schedule 22.06.2020

Я выясняю ответ из-за предложения @alawani. Это сработало для меня, если вы, ребята, заметили какую-то проблему, пожалуйста, поправьте меня. Проблема заключалась в том, что, как упоминалось в ответе, код переопределял существующий файл, поэтому этот код проверяет, существует ли файл, если он существует, тогда он просто пройдет, иначе он переименует его.

import os
path = os.chdir("/home/samipkarki/Pictures/Wallpapers")
value = 1
for file in os.listdir(path):
    print(os.listdir(path))
    new_filename = f'wallpaper{value}.jpg'
    if os.path.exists(new_filename):
        pass
    else:
        os.rename(file, new_filename)
        value += 1
person Community    schedule 24.06.2020