FSEvents - узнать, что было изменено в целевой директории
Я просто настроил FSEvent
для того, чтобы контролировать состояние целевой папки. Это работает просто отлично, потому что я получаю уведомление каждый раз, когда происходит изменение, и мне также дается путь к подкаталогу, в котором произошло изменение. Но что, если я захочу понять, какая операция была выполнена? Был ли файл добавлен, изменен, переименован или удален?
В библиотеке разработчика Mac я читаю это, используя постоянные события
"Вы можете узнать, какие файлы были изменены, даже когда ваше приложение не запущено. Это может значительно упростить такие задачи, как резервное копирование измененных файлов, проверка измененных зависимостей в многофайловых проектах и т. д.".
но если я правильно понял, это просто способ сравнить текущее состояние каталога с предыдущим, определенным идентификатором события. Опять же, я бы только получил путь к подкаталогу, где произошло изменение.
Мой вопрос: действительно ли мне нужно "вручную" делать снимки состояния моего каталога в разное время, создавая Directory Hierarchy Snapshots
и позже сравните их, чтобы узнать, какие операции выполняются во время между моментальными снимками? Разве нет более быстрого пути?
1 ответ
Я сделал следующее, чтобы иметь возможность различать различные операции над файлами внутри папки, которая просматривается с помощью FSEvent
(файл добавлен, файл переименован, файл удален и файл изменен).
Я создал объект File
со следующими свойствами (вы можете получить столько, сколько хотите, позвонив attributesOfItemAtPath:error:
):
@property (strong) NSString *name;
@property (strong) NSString *type;
@property (strong) NSDate *creationDate;
@property (strong) NSDate *modificationDate;
@property (strong) NSString *hash;
@property (strong) NSString *path;
Можно заполнить NSMutableArray
Файловые объекты следующим образом:
NSMutableArray *files = [[NSMutableArray alloc] init];
NSString *dirPath = //directory you are watching
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *theFiles = [fileManager contentsOfDirectoryAtURL:[NSURL fileURLWithPath:dirPath]
includingPropertiesForKeys:[NSArray arrayWithObject:NSURLNameKey]
options:NSDirectoryEnumerationSkipsHiddenFiles
error:nil];
NSArray* fileNames = [theFiles valueForKeyPath:@"lastPathComponent"];
if ( [fileNames count] > 0 ) {
for (NSInteger i=0; i<[fileNames count]; i=i+1) {
NSString *currentPath = [dirPath stringByAppendingString:[fileNames objectAtIndex:i]];
NSError *error;
NSDictionary *fileInfo = [fileManager attributesOfItemAtPath:currentPath error:&error];
File *currentFile = [[File alloc] initWithName:[fileNames objectAtIndex:i]
withType:fileInfo.fileType
withPath:currentPath
withHash: //get file hash
withCreationDate:fileInfo.fileCreationDate
andWithModificationDate:fileInfo.fileModificationDate];
[files addObject:currentFile];
}
Если каталог содержит подпапки, достаточно повторить этот процесс для каждой подпапки, возвращая и массив объектов File.
Чтобы понять, какая операция была выполнена, теперь достаточно сопоставить собранную ранее информацию (сохраненную в NSMutableArray *oldSnap
) и после обратного вызова (сохраняется в NSMutableArray *newSnap
)из FSEvent
, Сначала необходимо сопоставить файлы в oldSnap
с одним в newSnap
а потом наоборот.
Если в oldSnap
есть файл с заданным именем, который отсутствует в newSnap
, это означает, что этот файл был либо удален, либо переименован. Если есть файл с таким же хешем в newSnap
, затем файл был переименован; иначе он был удален из папки.
Завершение сравнения, если есть файл в newSnap
с другим fileModificationDate
от того же имени в oldSnap
, этот файл был изменен. Если в newSnap есть файл, который отсутствует в oldSnap
этот файл недавно добавлен.
Я еще не нашел решение, касающееся как переименования, так и изменения файла. Надеюсь, что этот ответ может помочь другим!