Retrieve file creation or modification date
Asked Answered
P

7

25

I'm using this piece of code to try to retrieve the last modified date of a file:

NSError *error = nil;
NSDictionary *attributes = [[NSFileManager defaultManager] attributesOfItemAtPath: myFilePath error:&error];

        if (attributes != nil) {
            NSDate *date = (NSDate*)[attributes objectForKey: NSFileModificationDate];
            NSLog(@"Date modiifed: %@", [date description]);
        }
        else {
            NSLog(@"Not found");
        }

This works well for files in the main bundle but not if the file is located in a subdirectory of the app's document folder, with myFilePath like this:

/Users/User/Library/Application Support/iPhone Simulator/6.0/Applications/The App ID Number/Documents/mySubdirectory/My Saved File

It keeps returning "not found".

I know the file is there, as I can view it with finder. I also tried removing the spaces in the file name but this had no effect.

The error log says no such file or directory, so it looks like something must've gone wrong when I tried to copy the file to the document directory.

Weird thing is, iterating through the document sub directory with contentsOfDirectoryAtPath shows the file as being present.

I've tried hard-coding the path and retrieving it programmatically, with:

*myFolder = [documentsDirectory stringByAppendingPathComponent:@"myFolder"];
*myFilePath = [myFolder stringByAppendingPathComponent:theFileName];

Can anyone see where I'm going wrong?

Petterson answered 21/11, 2012 at 16:19 Comment(9)
What are those three dots in the filename?Mown
Apologies; They represent the rest of the path, which I removed for brevity: /6.0/Applications/The App ID Number/ . I've edited the question and re-inserted them.Petterson
Is the file in your xcode project? created programmatically?Perfection
@Tin Can: It was. I then deleted it from the folder and added a different file manually to see if that would make a difference.Petterson
Pass an NSError to attributesOfItemAtPath and see what that says.Mown
@trojanfoe: it says no such file or directory, so it looks like something must've gone wrong when I tried to copy the file to the document directory. Weird thing is, iterating through the document sub directory with contentsOfDirectoryAtPath shows the file as being present.Petterson
@Petterson Sherlock Holmes: "When you have eliminated the impossible , whatever remains, however improbable, must be the truth." You say you can see the file in the Finder, so double-check your file path. Seems to be nothing wrong with your code otherwise.Winni
@trudyscousin: the path is retrieved programmatically: *myFolder = [documentsDirectory stringByAppendingPathComponent:@"myFolder"]; then *myFilePath = [myFolder stringByAppendingPathComponent:theFileName];Petterson
@Petterson So that path is non-nil? (At the risk of asking a stupid question...)Winni
S
23

Try this. I had same problem and solved with something like next:

NSURL *fileUrl = [NSURL fileURLWithPath:myFilePath];
NSDate *fileDate;
[fileUrl getResourceValue:&fileDate forKey:NSURLContentModificationDateKey error:&error];
if (!error)
{
//here you should be able to read valid date from fileDate variable
}

hope it helped ;)

Spirogyra answered 22/11, 2012 at 16:28 Comment(12)
thanks for the suggestion, although I'm not sure I understood it correctly. I tried this: NSURL *fileURL = [NSURL URLWithString:fullPathURLString]; NSDate *fileDate; [fileURL getResourceValue:&fileDate forKey:NSURLContentModificationDateKey error:&error]; if (!error) { NSLog(@"file modification date = %@", fileDate); }, and still got null.Petterson
Are you sure that file exists? Run application in simulator and check if fullPathURLString really exist on your file system. Probably you made some mistake while creating file path, otherwise I'm not sure what it can be. Also check what is contained in error object, maybe it gives you some hint for solving mystery :) if (!error) { NSLog(@"file modification date = %@", fileDate); } else { NSLog(@"Error: %@", error.localizedDescription); }Spirogyra
Yes, the files exist, although the file names contain spaces which have been replaced by %20. Could that be causing the problem?Petterson
Here's the error log: CFURLCopyResourcePropertyForKey failed because it was passed this URL which has no scheme: /Users/User/Library/Application%20Support/iPhone%20Simulator/6.0/Applications/A008CF0F-9EE1-42B5-921C-598FC8420279/Documents/downloads/Diagrams/8101-8101N%20Harsco%20Week%20.docPetterson
It looks to me that file is corrupted or something. Maybe it is not able to read doc file. Have you tried if it's working with .txt file?Spirogyra
Yes, .txt files produce the same outcome.Petterson
I have no idea what it could be!Spirogyra
Hey, no problem. Thank you very much for your efforts anyway.Petterson
No problem and tx. If somehow I find out how to deal with this I'll let you know ;)Spirogyra
Please don’t accept answers unless they actually solve your problem, otherwise it’s an indication for other users that this is indeed represents a solutions. Where it might not be the case.Oxeyed
It's a good answer, however you should check for error using the return value from [NSURL getResourceValue::] and not the existence of the NSError object.Mown
Make the url like this: NSURL *fileUrl = [NSURL fileURLWithPath:filePath];Kingfish
L
38

Swift 3 solution:

func fileModificationDate(url: URL) -> Date? {
    do {
        let attr = try FileManager.default.attributesOfItem(atPath: url.path)
        return attr[FileAttributeKey.modificationDate] as? Date
    } catch {
        return nil
    }
}
Lenin answered 6/11, 2016 at 8:25 Comment(0)
S
23

Try this. I had same problem and solved with something like next:

NSURL *fileUrl = [NSURL fileURLWithPath:myFilePath];
NSDate *fileDate;
[fileUrl getResourceValue:&fileDate forKey:NSURLContentModificationDateKey error:&error];
if (!error)
{
//here you should be able to read valid date from fileDate variable
}

hope it helped ;)

Spirogyra answered 22/11, 2012 at 16:28 Comment(12)
thanks for the suggestion, although I'm not sure I understood it correctly. I tried this: NSURL *fileURL = [NSURL URLWithString:fullPathURLString]; NSDate *fileDate; [fileURL getResourceValue:&fileDate forKey:NSURLContentModificationDateKey error:&error]; if (!error) { NSLog(@"file modification date = %@", fileDate); }, and still got null.Petterson
Are you sure that file exists? Run application in simulator and check if fullPathURLString really exist on your file system. Probably you made some mistake while creating file path, otherwise I'm not sure what it can be. Also check what is contained in error object, maybe it gives you some hint for solving mystery :) if (!error) { NSLog(@"file modification date = %@", fileDate); } else { NSLog(@"Error: %@", error.localizedDescription); }Spirogyra
Yes, the files exist, although the file names contain spaces which have been replaced by %20. Could that be causing the problem?Petterson
Here's the error log: CFURLCopyResourcePropertyForKey failed because it was passed this URL which has no scheme: /Users/User/Library/Application%20Support/iPhone%20Simulator/6.0/Applications/A008CF0F-9EE1-42B5-921C-598FC8420279/Documents/downloads/Diagrams/8101-8101N%20Harsco%20Week%20.docPetterson
It looks to me that file is corrupted or something. Maybe it is not able to read doc file. Have you tried if it's working with .txt file?Spirogyra
Yes, .txt files produce the same outcome.Petterson
I have no idea what it could be!Spirogyra
Hey, no problem. Thank you very much for your efforts anyway.Petterson
No problem and tx. If somehow I find out how to deal with this I'll let you know ;)Spirogyra
Please don’t accept answers unless they actually solve your problem, otherwise it’s an indication for other users that this is indeed represents a solutions. Where it might not be the case.Oxeyed
It's a good answer, however you should check for error using the return value from [NSURL getResourceValue::] and not the existence of the NSError object.Mown
Make the url like this: NSURL *fileUrl = [NSURL fileURLWithPath:filePath];Kingfish
C
6

Here is a Swift like solution of @zvjerka24 answer:

func lastModified(path: String) -> NSDate? {
    let fileUrl = NSURL(fileURLWithPath: path)
    var modified: AnyObject?
    do {
        try fileUrl.getResourceValue(&modified, forKey: NSURLContentModificationDateKey)
        return modified as? NSDate
    } catch let error as NSError {
        print("\(#function) Error: \(error)")
        return nil
    }
}
Centreboard answered 30/8, 2016 at 20:12 Comment(0)
P
3

If you get the error:

"CFURLCopyResourcePropertyForKey failed because it was passed this URL which has no scheme"

You can try to solve this by appending "file:///" to your NSString file path before converting it to NSURL, it worked in my case.

Pilewort answered 4/2, 2013 at 19:31 Comment(1)
It works but you should use -fileURLWithPath: instead of adding file:/// prefix.Duffel
T
3

Can also do:

NSURL* file = ...
NSError* error;`
NSDate *creationDate = [[NSFileManager defaultManager] attributesOfItemAtPath:file.path error:&error].fileCreationDate;
Tamtam answered 21/12, 2015 at 4:24 Comment(0)
S
1

For any file in macOS system we can easily get modification date by using any of below mentioned options:

Way 1:

  • NSString *path = @"path to file";
  • NSError *err = nil;
  • NSDictionary *dic2 = [[NSFileManager defaultManager] attributesOfItemAtPath:path error:&err];
  • NSLog(@"File modification Date:%@", dic2[NSFileModificationDate]);

Way 2:

  • MDItemRef itemRef = MDItemCreate(kCFAllocatorDefault, (__bridge CFStringRef)path);
  • NSArray *attributeNames = (__bridge NSArray *)MDItemCopyAttributeNames(itemRef);
  • NSDictionary *attributes = (__bridge NSDictionary *) MDItemCopyAttributes(itemRef, (__bridge CFArrayRef) attributeNames);

  • CFDateRef modifDate = MDItemCopyAttribute(itemRef, kMDItemContentModificationDate);

  • NSDate* modificationDate = (__bridge NSDate*) modifDate;
  • NSLog(@"Modification Date%@", modificationDate);

You can also print various other attributes provided by MDItem : NSLog(@"All attributes%@", attributes);

Stamps answered 25/2, 2019 at 7:52 Comment(0)
I
0

Usage:

let url = (myUrl)
url.creationDate
url.modificationDate

Extension

extension URL {

    var creationDate : Date? {
        return (
            try? resourceValues(
                forKeys: [
                    .creationDateKey
                ]
            )
        )?.creationDate
    }
    
    var modificationDate : Date? {
        return (
            try? resourceValues(
                forKeys: [
                    .contentModificationDateKey
                ]
            )
        )?.contentModificationDate
    }

}
Implied answered 27/7, 2024 at 22:56 Comment(1)
This has already been answered here. Note that the resource values can also be set. Using a computed property approach (a get without a set) won’t allow you to change its value.Splay

© 2022 - 2025 — McMap. All rights reserved.