zpasternack
zpasternack

Reputation: 17898

Simple way to get a "shortened" version of a file path

Maybe "shortened" isn't the proper term; I'll try to explain.

I want to display the path to a file to the user, but I want to do so in such a way that shortens the home path to ~, and the root path to /.

For example, the path to a file, MyImage.png, in a given user's home directory, will be something like:

/Volumes/SSD/Users/zach/Pictures/MyImage.png

But what I want is:

~/Pictures/MyImage.png

Similarly, a file relative to root, like this:

/Volumes/SSD/Applications/MyApp.app

Should look like:

/Applications/MyApp.app

It's simple enough to replace the user's home path with ~, like:

NSString* shortPath = [fullPath stringByReplacingOccurrencesOfString:NSHomeDirectory() 
                                withString:@"~"];

But that won't solve it for the root-relative path case.

I was hoping the answer was "call this POSIX function that does all the magic for you", but I haven't been able to find anything like that. Am I missing something?

Update: @Volker's comment below is accurate: stringByAbbreviatingWithTildeInPath does handle the home path case, if not the root-relative case. Problem with that is, it's doing basically what my code above does (replacing NSHomeDirectory() with "~"). That's fine for a non-sandboxed app, but in a sandboxed app, NSHomeDirectory() won't be /Users/zach, but something like /Users/zach/Library/Containers/com.mycompany.myapp/Data/. So if I pass it a path like "/Users/zach/Pictures/MyImage.png", no replacement will actually take place.

For now I'm just doing the replacement myself (as above, but by getting the real home directory path, as I wrote about here).

Upvotes: 0

Views: 313

Answers (1)

pointum
pointum

Reputation: 3177

For displaying file names it's recommended to use special NSFileManager methods instead of operating on path strings. Localization and stuff.
Namely displayNameAtPath: and componentsToDisplayForPath:.

The later gets rid of "Volumes" string automatically. As for getting rid of root volume name consider comparing Volume IDs. E.g.:

    NSURL* rootURL = [NSURL fileURLWithPath:@"/"];
    NSData* rootID = nil;
    [rootURL getResourceValue:&rootID forKey:NSURLVolumeIdentifierKey error:nil];

    NSURL* fileURL = [NSURL fileURLWithPath:@"/Volumes/SSD/Applications/"];
    NSData* fileVolumeID = nil;
    [fileURL getResourceValue:&fileVolumeID forKey:NSURLVolumeIdentifierKey error:nil];

    if ([fileVolumeID isEqualToData:rootID])
    {
        // Strip "/Volumes/*/" part of path if any, then get display components
    }

Upvotes: 1

Related Questions