Get directory contents in date modified order
23,615
Solution 1
nall's code above pointed me in the right direction, but I think there are some mistakes in the code as posted above. For instance:
-
Why is
filesAndProperties
allocated usingNMutableDictonary
rather than anNSMutableArray
? -
The code above is passing the wrong parameter forNSDictionary* properties = [[NSFileManager defaultManager] attributesOfItemAtPath:NSFileModificationDate error:&error];
attributesOfItemAtPath
- it should beattributesOfItemAtPath:path
-
Your are sorting the
files
array, but you should be sortingfilesAndProperties
.
I have implemented the same, with corrections, and using blocks and posted below:
NSArray *searchPaths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
NSString* documentsPath = [searchPaths objectAtIndex: 0];
NSError* error = nil;
NSArray* filesArray = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:documentsPath error:&error];
if(error != nil) {
NSLog(@"Error in reading files: %@", [error localizedDescription]);
return;
}
// sort by creation date
NSMutableArray* filesAndProperties = [NSMutableArray arrayWithCapacity:[filesArray count]];
for(NSString* file in filesArray) {
NSString* filePath = [iMgr.documentsPath stringByAppendingPathComponent:file];
NSDictionary* properties = [[NSFileManager defaultManager]
attributesOfItemAtPath:filePath
error:&error];
NSDate* modDate = [properties objectForKey:NSFileModificationDate];
if(error == nil)
{
[filesAndProperties addObject:[NSDictionary dictionaryWithObjectsAndKeys:
file, @"path",
modDate, @"lastModDate",
nil]];
}
}
// sort using a block
// order inverted as we want latest date first
NSArray* sortedFiles = [filesAndProperties sortedArrayUsingComparator:
^(id path1, id path2)
{
// compare
NSComparisonResult comp = [[path1 objectForKey:@"lastModDate"] compare:
[path2 objectForKey:@"lastModDate"]];
// invert ordering
if (comp == NSOrderedDescending) {
comp = NSOrderedAscending;
}
else if(comp == NSOrderedAscending){
comp = NSOrderedDescending;
}
return comp;
}];
Solution 2
How about this:
// Application documents directory
NSURL *documentsURL = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
NSArray *directoryContent = [[NSFileManager defaultManager] contentsOfDirectoryAtURL:documentsURL
includingPropertiesForKeys:@[NSURLContentModificationDateKey]
options:NSDirectoryEnumerationSkipsHiddenFiles
error:nil];
NSArray *sortedContent = [directoryContent sortedArrayUsingComparator:
^(NSURL *file1, NSURL *file2)
{
// compare
NSDate *file1Date;
[file1 getResourceValue:&file1Date forKey:NSURLContentModificationDateKey error:nil];
NSDate *file2Date;
[file2 getResourceValue:&file2Date forKey:NSURLContentModificationDateKey error:nil];
// Ascending:
return [file1Date compare: file2Date];
// Descending:
//return [file2Date compare: file1Date];
}];
Solution 3
Simpler...
NSArray* filelist_sorted;
filelist_sorted = [filelist_raw sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
NSDictionary* first_properties = [[NSFileManager defaultManager] attributesOfItemAtPath:[NSString stringWithFormat:@"%@/%@", path_thumb, obj1] error:nil];
NSDate* first = [first_properties objectForKey:NSFileModificationDate];
NSDictionary* second_properties = [[NSFileManager defaultManager] attributesOfItemAtPath:[NSString stringWithFormat:@"%@/%@", path_thumb, obj2] error:nil];
NSDate* second = [second_properties objectForKey:NSFileModificationDate];
return [second compare:first];
}];
Solution 4
It's too slow
[[NSFileManager defaultManager]
attributesOfItemAtPath:NSFileModificationDate
error:&error];
Try this code:
+ (NSDate*) getModificationDateForFileAtPath:(NSString*)path {
struct tm* date; // create a time structure
struct stat attrib; // create a file attribute structure
stat([path UTF8String], &attrib); // get the attributes of afile.txt
date = gmtime(&(attrib.st_mtime)); // Get the last modified time and put it into the time structure
NSDateComponents *comps = [[NSDateComponents alloc] init];
[comps setSecond: date->tm_sec];
[comps setMinute: date->tm_min];
[comps setHour: date->tm_hour];
[comps setDay: date->tm_mday];
[comps setMonth: date->tm_mon + 1];
[comps setYear: date->tm_year + 1900];
NSCalendar *cal = [NSCalendar currentCalendar];
NSDate *modificationDate = [[cal dateFromComponents:comps] addTimeInterval:[[NSTimeZone systemTimeZone] secondsFromGMT]];
[comps release];
return modificationDate;
}
Comments
-
nevan king over 3 years
Is there an method to get the contents of a folder in a particular order? I'd like an array of file attribute dictionaries (or just file names) ordered by date modified.
Right now, I'm doing it this way:
- get an array with the file names
- get the attributes of each file
- store the file's path and modified date in a dictionary with the date as a key
Next I have to output the dictionary in date order, but I wondered if there's an easier way? If not, is there a code snippet somewhere which will do this for me?
Thanks.
-
nevan king over 14 yearsThanks for the answer. There seems to be a few things that won't work with the iPhone SDK here (NSURLContentModificationDateKey and some other NSURL methods).
-
nevan king over 14 yearsI've started trying to change it to work with the iPhone SDK, but getResourceValue doesn't exist there. I'll look for an array sort for iPhone.
-
nall over 14 yearsnevan, I updated this to work within the constraints of the iPhone SDK
-
Roger over 13 yearsLots of little bugs in this code fragment ... I don't think this code is tested on iOS.
-
Jonathan. over 12 yearsTo invert the ordering you can just multiply the comparison result by -1.
-
Admin over 12 yearsTo invert the ordering you can just use
return [[path2 objectForKey:@"lastModDate"] compare:[path1 objectForKey:@"lastModDate"]];
-
Ivan Kovacevic over 11 yearsI was just looking for the solution for this myself and ended up using the above code. So I've put it here cause I think its cleaner than what others have provided ;)
-
ski_squaw over 10 yearsThis is much faster. 4x faster in my tests. I ran into one bug with this though. My gmtime is returning UTC not GMT. Some times had a one hour difference which caused problems.
-
ski_squaw over 10 yearsAdjust code as follows: NSCalendar *cal = [NSCalendar currentCalendar]; NSTimeZone *tz = [NSTimeZone timeZoneWithAbbreviation:[[NSString alloc] initWithUTF8String:date->tm_zone]]; cal.timeZone = tz;
-
Maciej Swic over 9 yearsYou need to #import "sys/stat.h"
-
DJTano over 6 yearswhat is path_thumb ?