这是一个不对日期使用字符串比较并在枚举器中预取修改时间的函数:
+ (NSArray<NSURL *> *)deleteFilesOlderThan:(NSDate *)earliestDateAllowed
inDirectory:(NSURL *)directory {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSDirectoryEnumerator<NSURL *> *enumerator =
[fileManager enumeratorAtURL:directory
includingPropertiesForKeys:@[ NSURLContentModificationDateKey ]
options:0
errorHandler:^BOOL(NSURL *_Nonnull url, NSError *_Nonnull error) {
NSLog(@"Failed while enumerating directory '%@' for files to "
@"delete: %@ (failed on file '%@')",
directory.path, error.localizedDescription, url.path);
return YES;
}];
NSURL *file;
NSError *error;
NSMutableArray<NSURL *> *filesDeleted = [NSMutableArray new];
while (file = [enumerator nextObject]) {
NSDate *mtime;
if (![file getResourceValue:&mtime forKey:NSURLContentModificationDateKey error:&error]) {
NSLog(@"Couldn't fetch mtime for file '%@': %@", file.path, error);
continue;
}
if ([earliestDateAllowed earlierDate:mtime] == earliestDateAllowed) {
continue;
}
if (![fileManager removeItemAtURL:file error:&error]) {
NSLog(@"Couldn't delete file '%@': %@", file.path, error.localizedDescription);
continue;
}
[filesDeleted addObject:file];
}
return filesDeleted;
}
如果您不关心被删除的文件,您可以让它返回BOOL
以指示是否有任何错误,或者只是void
想尽最大努力尝试。
要有选择地保留一些文件,请向应该匹配要保留的文件的函数添加一个正则表达式参数,并在 while 循环中添加一个检查(似乎最适合您的用例),或者如果有一个离散量具有不同模式的文件,您可以接受NSSet
带有要保留的文件名的文件,并在继续删除之前检查是否包含在集合中。
这里也只是提到这一点,因为它可能与某些人相关:iOS 和 OSX 上的文件系统不会以超过一秒的精度存储 mtime,因此如果您需要毫秒精度或类似精度,请注意这一点。
如果您愿意,可以将相应的测试用例放入您的测试套件中:
@interface MCLDirectoryUtilsTest : XCTestCase
@property NSURL *directory;
@end
@implementation MCLDirectoryUtilsTest
- (void)setUp {
NSURL *tempdir = [NSURL fileURLWithPath:NSTemporaryDirectory() isDirectory:YES];
self.directory = [tempdir URLByAppendingPathComponent:[NSUUID UUID].UUIDString isDirectory:YES];
NSFileManager *fileManager = [NSFileManager defaultManager];
[fileManager createDirectoryAtURL:self.directory
withIntermediateDirectories:YES
attributes:nil
error:nil];
}
- (void)tearDown {
NSFileManager *fileManager = [NSFileManager defaultManager];
[fileManager removeItemAtURL:self.directory error:nil];
}
- (void)testDeleteFilesOlderThan {
NSFileManager *fileManager = [NSFileManager defaultManager];
// Create one old and one new file
[fileManager createFileAtPath:[self.directory URLByAppendingPathComponent:@"oldfile"].path
contents:[NSData new]
attributes:@{
NSFileModificationDate : [[NSDate new] dateByAddingTimeInterval:-120],
}];
[fileManager createFileAtPath:[self.directory URLByAppendingPathComponent:@"newfile"].path
contents:[NSData new]
attributes:nil];
NSArray<NSURL *> *filesDeleted =
[MCLUtils deleteFilesOlderThan:[[NSDate new] dateByAddingTimeInterval:-60]
inDirectory:self.directory];
XCTAssertEqual(filesDeleted.count, 1);
XCTAssertEqualObjects(filesDeleted[0].lastPathComponent, @"oldfile");
NSArray<NSString *> *contentsInDirectory =
[fileManager contentsOfDirectoryAtPath:self.directory.path error:nil];
XCTAssertEqual(contentsInDirectory.count, 1);
XCTAssertEqualObjects(contentsInDirectory[0], @"newfile");
}