Search code examples
objective-cnsurlnsfilemanager

How would I resolve a relative path in Objective-C?


I am trying the code below to see if I can get it to expand the absolute path for those locations so that I can use them for actions with NSFileManager which fail when I use the tilde and relative paths.

I am working on a command-line app in Xcode in Objective-C. I can run the program from the command-line and it expands the path for me, but from the target in Xcode I am passing in values for the command-line arguments using $PROJECT_DIR and $HOME to get me part of the way there. The trouble is I need to get to $PROJECT_DIR/.. which is not resolving with NSFilemanager.

It does not appear that URLByResolvingSymlinksInPath or URLByStandardizingPath work as I am expecting. Is there something else that I should be doing?

BOOL isDir = TRUE;
for (NSString *path in @[@"~/", @".", @".."]) {
    NSURL *url = [[[NSURL URLWithString:path] URLByResolvingSymlinksInPath] URLByStandardizingPath];
    DebugLog(@"path: %@", url.absoluteString);
    DebugLog(@"Exists: %@", [[NSFileManager defaultManager] fileExistsAtPath:url.path isDirectory:&isDir] ? @"YES" : @"NO");
}

Update: I am using realpath from stdlib to resolve the path and created the following method though I do not understand this C function. Specifically I do not know waht the resolved value is or how I would use it. I do see to get the expected return value.

- (NSString *)resolvePath:(NSString *)path {
    NSString *expandedPath = [[path stringByExpandingTildeInPath] stringByStandardizingPath];
    const char *cpath = [expandedPath cStringUsingEncoding:NSUTF8StringEncoding];
    char *resolved = NULL;
    char *returnValue = realpath(cpath, resolved);

//    DebugLog(@"resolved: %s", resolved);
//    DebugLog(@"returnValue: %s", returnValue);

    return [NSString stringWithCString:returnValue encoding:NSUTF8StringEncoding];
}

Solution

  • Below is my solution which is working well which uses a lower level C function which I was trying to avoid. It is working for my purposes. The full project which uses is available on GitHub with the method I created for Objective-C below.

    https://github.com/brennanMKE/Xcode4CodeSnippets/tree/master/SnippetImporter

    - (NSString *)resolvePath:(NSString *)path {
        NSString *expandedPath = [[path stringByExpandingTildeInPath] stringByStandardizingPath];
        const char *cpath = [expandedPath cStringUsingEncoding:NSUTF8StringEncoding];
        char *resolved = NULL;
        char *returnValue = realpath(cpath, resolved);
    
        if (returnValue == NULL && resolved != NULL) {
            printf("Error with path: %s\n", resolved);
            // if there is an error then resolved is set with the path which caused the issue
            // returning nil will prevent further action on this path
            return nil;
        }
    
        return [NSString stringWithCString:returnValue encoding:NSUTF8StringEncoding];
    }