Python поиск измененных файлов

Как найти измененные файлы в Python

Я хочу отслеживать папку и видеть, добавляются ли какие-либо новые файлы или изменяются существующие файлы. Проблема в том, что не гарантируется, что моя программа будет работать все время (поэтому inotify основанные решения могут не подходить здесь). Мне нужно кэшировать состояние последнего сканирования, а затем при следующем сканировании мне нужно сравнить его с последним сканированием перед обработкой файлов.

Каковы альтернативы для достижения этого в Python 2.7?

Примечание 1: Обработка файлов стоит дорого, поэтому я пытаюсь обработать файлы, которые не были изменены в это время. Итак, если файл переименовывается только (в отличие от изменения содержимого файла), я также хотел бы обнаружить это и пропустить обработку.

Примечание 2: Меня интересует только решение для Linux, но я бы не стал жаловаться, если будут добавлены ответы для других платформ.

4 ответа

Есть несколько способов обнаружить изменения в файлах. Одни легче обмануть, чем другие. Не похоже, что это проблема безопасности; больше похоже на добросовестность, и вам просто нужно обнаруживать изменения без необходимости перехитрить противника.

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

Читайте также:  Php select count from database

Вы можете посмотреть на иноды, например, ls -li , Номер inode файла может измениться, если изменения включают создание нового файла и удаление старого; вот как emacs например, обычно изменяет файлы. Попробуйте изменить файл с помощью стандартного инструмента, используемого вашей организацией, и сравните inode до и после; но имейте в виду, что даже если это не изменится в этот раз, оно может измениться при некоторых обстоятельствах. os.stat скажет вам номера инодов.

Вы можете посмотреть на содержимое файлов. cksum вычисляет небольшую контрольную сумму CRC для файла; легко победить, если кто-то хочет. Такие программы, как sha256sum вычислить безопасный хеш; невозможно изменить файл без изменения такого хеша. Это может быть медленно, если файлы большие. hashlib Модуль будет вычислять несколько видов безопасных хэшей.

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

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

Источник

Мониторинг за изменениями файловой системы

В поисках готового велосипеда для решения задачи мониторинга за изменениями в ФС с поддержкой linux+freebsd наткнулся на приятную python либу watchdog (github, packages.python.org). Которая помимо интересных мне ОС поддерживает также MacOS (есть своя специфика) и Windows.
Тем, кому данный вопрос интересен и кого не отпугнет индийское происхождение автора, прошу .

Установка

Можно взять готовую версию из PIP:
$ pip install watchdog
Сам PIP ставится как пакет python-pip, порт devel/py-pip, etc.
Либо собрать из исходников через setup.py.

Достаточно подробно все расписано в оригинальном руководстве. Правда там описание версии 0.5.4, а сейчас актуальна 0.6.0. Однако, вся разница в правке копирайтов и замене отступа в 4 пробела на отступ в 2. «Google code style» 🙂

Вообще, там довольно много особенностей сборки по версиям самого python так и по целевой платформе. Они все описаны по ссылке выше, но если будет нужно, допишу в статью вкратце на русском.

Кроме того, собрать модуль можно на несовместимой ОС, но тогда в дело вступится fallback-реализация, делающая «слепки» структуры ФС с последующими сравнениями. Возможно, так кто-то и делал у себя при решении подобной задачи 🙂

Сам же я пробовал собрать под ubuntu 11.4 и freebsd-8.2 RELEASE, каких-либо проблем при сборке и работе не возникло.

Базовый пример

Предположим, что нас интересуют изменения по некоему пути /path/to/smth, связанные с созданием, удалением и переименованием файлов и директорий.

from watchdog.observers import Observer from watchdog.events import FileSystemEventHandler 

Класс Observer выбирается в /observers/__init__.py исходя из возможностей вашей ОС, так что нет необходимости самостоятельно решать, что же выбрать.
Класс FileSystemEventHandler является базовым классом обработчика событий изменения. Он мало что умеет, но мы научим его потомка:

class Handler(FileSystemEventHandler): def on_created(self, event): print event def on_deleted(self, event): print event def on_moved(self, event): print event 

Полный список методов можно увидеть в самом FileSystemEventHandler.dispatch: on_modified, on_moved, on_created, on_deleted.

observer = Observer() observer.schedule(Handler(), path='/path/to/smth', recursive=True) observer.start() 

Observer является относительно далеким потомком threading.Thread, соотвественно после вызова start() мы получаем фоновый поток, следящий за изменениями. Так что если скрипт сразу завершится, то ничего толкового мы не получим. Реалиация ожидания зависит в первую очередь от применения модуля в реальном проекте, сейчас же можно просто сделать костыль:

try: while True: time.sleep(0.1) except KeyboardInterrupt: observer.stop() observer.join() 

Ждем событий изменений ФС до прихода Ctrl+C (SIGINT), после чего говорим нашему потоку завершиться и ждем, пока он это выполнит.

Запускаем скрипт, идем по нашему пути и:

# mkdir foo # touch bar # mv bar baz # cd foo/ # mkdir foz # mv ../baz ./quz # cp ./quz ../hw # cd .. # rm -r ./foo # rm -f ./* 

В методы нашего класса Handler в поле event приходят потомки FileSystemEvent, перечисленные в watchdog/events.py.
У всех есть свойства src_path, is_directory, event_type («created», «deleted», и т.п.). Для события moved добавляется свойство dest_path.

Ну если вы больше ничего не хотите… А разве ещё что-нибудь есть?

  • * любые символы
  • ? любой единичный символ
  • [seq] любой единичный символ из указанных
  • [!seq] любой единичный символ НЕ из указанных
class Handler(PatternMatchingEventHandler): pass event_handler = Handler( patterns = ['*.py*'], ignore_patterns = ['cache/*'], ignore_directories = True, case_sensitive = False ) observer = Observer() observer.schedule(event_handler, path='/home/LOGS/', recursive=True) 

RegexMatchingEventHandler делает тоже самое, но с явным указанием regexp-выражений в конструкторе:

class Handler(RegexMatchingEventHandler): pass event_handler = Handler( regexes = ['\.py.?'], ignore_regexes = ['cache/.*'], ignore_directories = True, case_sensitive = False ) 

PatternMatchingEventHandler внутри себя в итоге транслирует шаблоны в регулярки, так что должен работать медленнее из-за наличия такого оверхеда.

Наконец, LoggingEventHandler выводит все в лог через logging.info().

— Вот и все. Может кому пригодится.

P.S.
При слежении за директорией, в которой (и в ее дочерних) содержатся папки/файлы не с ascii именованием, возникнет исключение exceptions.UnicodeEncodeError в глубинах watchdog’а. В Linux (inotify) он возникает в watchdog.observers.inotify.Inotify._add_watch.
Причина — чтение содержимого в ascii кодировке.
Для исправления ситуации можно пропатчить метод:

from watchdog.observers.inotify import Inotify _save = Inotify._add_watch Inotify._add_watch = lambda self, path, mask: _save(self, path.encode('utf-8'), mask) 

Вот пример исходной строки, и ее repr() до и после обработки encode():

/home/atercattus/.wine/drive_c/users/Public/Рабочий стол u'/home/atercattus/.wine/drive_c/users/Public/\u0420\u0430\u0431\u043e\u0447\u0438\u0439 \u0441\u0442\u043e\u043b' '/home/atercattus/.wine/drive_c/users/Public/\xd0\xa0\xd0\xb0\xd0\xb1\xd0\xbe\xd1\x87\xd0\xb8\xd0\xb9 \xd1\x81\xd1\x82\xd0\xbe\xd0\xbb' 

Источник

Русские Блоги

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


import os,os.path,re,time

filelist=[]
path = 'F:\hbtv'

t=time.strptime("2010-09-15 00:00:00", "%Y-%m-%d %H:%M:%S")
t= time.mktime(t)


for root, dirs, files in os.walk(path):
for file in files:
path= os.path.join(root, file)
if (not re.match(r".*(\.svn|\.project|html\.\d+|Thumbs\.db).*", path)):# and os.path.getmtime(file)>t :
filelist.append(path)

for i in filelist:
if os.path.getmtime(i)>t:
print i#,time.strftime('%Y-%m-%d %H:%M:%S',time.gmtime(os.path.getmtime(i)))

Интеллектуальная рекомендация

LiveVideostack Online Season 5 (13): высокопроизводительное видео

Вспышка видео бизнеса в сценарии 4G/5G и требования пользователя для более высокого качества (в прямом эфире, короткое видео, видео на -Деманд), более высокое качество изображения означает больше вычи.

Чем занимаются back-end программисты?

Внимание друзья! Редактор здесь, чтобы послать всем внимание и преимущества: Выполните поиск в общедоступной учетной записи WeChat «Quick Learning Java» и следуйте за вами, чтобы получить .

Сделай сам свой линейный стол с линейным хранилищем в C ++

Пожалуйста, укажите источник, спасибо ~ http: //blog.csdn.net/hongkangwl/article/details/21802073 Можно сказать, что линейная таблица является самой простой структурой данных, и ее описание:конечная п.

Вопросник письменного экзамена Huawei из 6 символов

Введите строку и найдите набор символов, содержащихся в строке Введите описание: Описание выхода: Пример ввода 1: Пример вывода 1: Личное решение таково: .

JUC -RENTRANTLOCK SUPPRONTION

Re etyrantlock, переводчик называется тяжелым замком, который является способом обеспечения безопасности потока. Это похоже на роль синхронизации, но каков его принцип реализации. После проверки многи.

Источник

Оцените статью