Употреба по не-предназначение - folder changes watcher с Mathematica

{ 8 април 2009 }

Във всекидневната си работа с компютър хората често се сблъскват с задачи, за които нямат предоставена автоматизация, и в много случаи е по-лесно сами да ги автоматизират отколкото да изпълняват многократно една и съща операция. И с подходящия инструмент създаването на автоматизиращо решение е доста просто.

Пиша тази тема, защото много от хората, които са запознати (дори поне малко) с Mathematica, я използват като система за извършване на символни изчисления и анализ. Но в програмата са включени и много други интересни и полезни функции, които са документирани така, че да не се налага на клиента да ги пише наново и да прекарва времето си в "детективска" работа (както се случва например с MSDN).

Със вградената си мощна пъддръжка на манипулация на низове и работа с директории и всякакъв вид файлове, Mathematica е идеална за създаването на малки скриптове за справяне със всекидневни проблеми.

Този път ще направим скрипт, чрез който се следи за промяна на някои файлове в определена директория.

Първо искаме да зададем директорията и файлът за запис на информацията:

projectDirectory="C:\\project\\";
projectHashSave="project.mx";

Сега да прочетем файловете във дадената директория, и във поддиректориите:

GetFilenames[] := Pick[#, StringMatchQ[#, __ ~~ "." ~~ __]] & /@ \
FileNames[__, {projectDirectory}, Infinity];

Използваме Pick[] за да изберем само файловете, без самите директории.

Следващата стъпка е да хешираме файловете и да ги запишем в... Всъщност Mathematica използва нещо, което може да се оприличи на hash_map. Също така Mathematica си има готова функция за хеширане на файл (отделно от функцията за хеширане на всичко друго):

projectHash[file_] := 0;
(projectHash[#] = FileHash[#]) & /@ projectFiles;
DumpSave[projectHashSave, projectHash];

С това завършва операцията за записване на промените във файла. Ето я като отделна функция:

projectUpdate[] := (
  projectFiles = GetFilenames[];
  projectHash[file_] := 0;
  (projectHash[#] = FileHash[#]) & /@ projectFiles;
  DumpSave[projectHashSave, projectHash];
);

За проверка кои файлове са променени, просто за всеки файл в дървото на директорията, сравняваме хеш-стойността му със записаната преди:

projectChanges[] := (
  << "project.mx";
  TprojectFiles = GetFilenames[];
  Print["Changed Files:"];
  If[FileHash[#] != projectHash[#], Print[#]] & /@ TprojectFiles;
);

Ето скрипта в действие:


Материали: project.nb