пятница, 26 марта 2010 г.

Скрипт копирования директории с фильтром файлов

Не так давно игровой движок, надо которым я работаю уже длительное время, был собран в статическую библиотеку. Возникла вот такая проблема: очень неудобно руками выбирать заголовочные файлы из папок проекта в отдельный include каталог библиотеки.
Соответственно появилась идея написать скрипт для автоматизации данного процесса. А так как уже давно интересуюсь скриптовым языком Python, то захотелось опробовать его на этой задаче.
По сути задача простая, и её можно решить множеством способов. Она сводится к обходу всех подкаталогов в заданном родительном и копирование указанного типа файлов и подкаталогов в указанное место.
В Python-не за работу с файлами и папками отвечает модуль os, с чтения документации по его возможностям я и начал. Но хотелось свести писанину к минимуму, и я решил ознакомиться с руководством более подробно. Через некоторое время была найдена функция с очень интересным названием:
copytree(src, dst[, symlinks=False[, ignore=None]])

которая находится в модуле shutil.
По ней сразу понятно, что она умеет копировать дерево каталогов а так же видно, что можно задавать игнорируемые файлы. Далее даётся подсказка, что файлы фильтруются при помощи функции:
ignore_patterns(*patterns)

Полностью конструкция, которая у меня получилась, выглядит так:
from_dir = "..\\..\\K5Engine"
to_dir = "..\\include"
shutil.copytree(from_dir, to_dir ,ignore = shutil.ignore_patterns("*.cpp",".svn"))

Осталась только одна проблема, если директория include уже создана, она не будет переписана. Опять поход в документацию для поиска функции удаления каталога.
Собственно вот она:
rmtree(path[, ignore_errors[, onerror]])

Далее весь полученный код собирается в один скрипт, который и решает поставленную задачу:
import os
import shutil

if __name__ == '__main__':
    from_dir = "..\\..\\K5Engine"
    to_dir = "..\\include"

    if os.path.isdir(to_dir):
        shutil.rmtree(to_dir)

    shutil.copytree(from_dir,to_dir ,ignore=shutil.ignore_patterns("*.cpp",".svn"))

На этом всё.