Python – OSError: [Errno 2] Нет такого файла или каталога

Я прочитал много вопросов по этой проблеме, но я заметил, что это происходит по многим причинам, и не нашел ответа на мою конкретную проблему. Дело в том, что я случайно удалил некоторые файлы и использовал photorec, чтобы попытаться их восстановить (у меня Ubuntu 16.04 Xenial). Проблема в том, что он восстановил более 2600 папок! Я пишу небольшой файловый сканер, чтобы избавиться от ненужных мне файлов - меня интересуют только файлы .py, .jpg, .png и .mp3. Вот код моего сканера:

import os

path=

for (path, dirs, files) in os.walk(path):
    for name in files:
        if name.endswith('.py') or name.endswith('.jpg') or name.endswith('.png') or name.endswith('.mp3'):
            continue
        else: os.remove(name)

Я определяю «путь» вручную, и я сделал тест, в котором я печатаю часть путей, каталогов и файлов, и он печатает то, что я хочу. Однако при запуске кода ниже он возвращает:

OSError: [Errno 2] No such file or directory: 'f0272560.java'

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

Заранее спасибо!


person DarthDante    schedule 22.09.2016    source источник
comment
Вы передаете только голое имя файла в os.remove(). Вы должны передать полный путь.   -  person John Gordon    schedule 23.09.2016


Ответы (1)


files list yielded by os.walk — это неполные имена файлов. Если они не находятся в рабочем каталоге, os.remove не может удалить их по неполным именам, потому что не знает, где их найти. Изменять:

os.remove(name)

to

os.remove(os.path.join(path, name))

поэтому вы передаете полный путь к файлу, а не только его имя.

Дополнительное примечание: хотя это прекрасно работает, если вам никогда не понадобится исходное определение path, перезапись его на цикл path из os.walk может привести к путанице. Возможно, вы захотите изменить имя одного из них, либо изменив имя верхнего уровня на rootdir, либо изменив имя переменной цикла на что-то другое (например, curdir).

person ShadowRanger    schedule 23.09.2016
comment
Большое спасибо! Мне было непонятно, как правильно пользоваться os.walk - person DarthDante; 23.09.2016
comment
@DarthDante: Яр, os.listdir сбивает с толку по тем же причинам. Для os.listdir я рекомендую заменить его на os.scandir (к сожалению, 3.5 или выше; до версии 3.5 вам нужен пакет PyPI scandir, чтобы использовать эквивалент scandir.scandir), где возвращаемые записи имеют атрибут .name для простого имени и .path для квалифицированного дорожка; для os.walk неплохая идея, чтобы первые две строки внутри цикла walk были qdirs = [os.path.join(path, d) for d in dirs], qfiles = [os.path.join(path, f) for f in files], чтобы вы могли перебирать qdirs/qfiles для предварительно определенных путей. - person ShadowRanger; 23.09.2016