Есть ли лучший способ удалить все файлы .py и .pyc в данном подкаталоге?

Я написал скрипт для удаления всех файлов .py и .pyc в заданном подкаталоге под названием «миграции». Конечная цель — удалить все файлы миграции из моего проекта django, поэтому есть несколько подпапок, называемых «миграции», и я хотел бы удалить все .py и .pyc (кроме init.py) из этих папок. Сценарий, который я написал ниже, работает, но я новичок в python и считаю, что должен быть лучший способ, чем все вложенные циклы. Какие-либо предложения? Это система Windows, которая все усложняет для меня.

import os
import sys

def delete_py(path, subfolder):
    try:
        if os.path.exists(path):
            for (root, dirs, files) in os.walk(path):
                for dir in dirs:
                    if dir == subfolder:
                        goto = os.path.join(root, dir)
                        for (root, dirs, files) in os.walk(goto):
                            for file in files:
                                if (file.lower().endswith('.py') | 
                                    file.lower().endswith('.pyc')) and 
                                    file != '__init__.py':
                                    print('file: ', file)
                                    # will change to os.remove once finsihed
    except:
        print('Unable to delete files')


if __name__ == "__main__":
    current = os.getcwd()
    delete_py(current, 'migrations')

person dpoiesz    schedule 28.01.2019    source источник
comment
Почему бы просто не указать путь migrations к os.walk()? Вы без нужды являетесь и всем остальным.   -  person Martijn Pieters    schedule 28.01.2019
comment
Обратите внимание, что вы не хотите использовать |! Это побитовое или, а не логическая логика ИЛИ. И str.endswith() берет набор опций для проверки, так что file.lower().endswith(('*.py', '*.pyc')) достаточно.   -  person Martijn Pieters    schedule 28.01.2019


Ответы (3)


Вы выполняете двойную работу, вызывая os.walk() для подкаталогов, которые уже будут обрабатываться внешним циклом os.walk().

Все, что вам нужно проверить, это если migrations является элементом в текущем пути root к обрабатываемому каталогу:

def delete_py(path, subfolder):
    for root, dirs, files in os.walk(path):
        if subfolder in root.split(os.sep):
            # has subfolder as a directory name in the path, delete .py files here
            for file in files:
                if file == '__init__.py':
                    continue
                if file.endswith(('.py', '.pyc')):
                    os.unlink(os.path.join(root, file))

Вы также можете просто использовать рекурсивный шаблон glob с модулем glob:

from itertools import chain

def delete_py(path, subfolder):
    pyfiles = glob.iglob(f'**/{subfolder}/**/*.py', recursive=True)
    pycfiles = glob.iglob(f'**/{subfolder}/**/*.pyc', recursive=True)
    for filename in chain(pyfiles, pycfiles):
        if os.path.basename(filename) == '__init__.py':
            continue
        os.unlink(filename)
person Martijn Pieters    schedule 28.01.2019
comment
Спасибо, так намного лучше. Просто пришлось изменить root.split(os.pathsep): на root.split(os.path.sep): - person dpoiesz; 28.01.2019
comment
@dpoiesz: извиняюсь за это, на самом деле это должно было быть os.sep. - person Martijn Pieters; 28.01.2019

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

person Scott Hunter    schedule 28.01.2019

просто используйте

  • для Linux "найти .-имя "*.pyc" -удалить"
  • для окон: "DEL /S /Q *.pyc"
person Gaurav Singh    schedule 09.05.2020