String Representations of File Paths

NSString provides a rich set of methods for manipulating strings as file-system paths. You can extract a path’s directory, filename, and extension, expand a tilde expression (such as “~me”) or create one for the user’s home directory, and clean up paths containing symbolic links, redundant slashes, and references to “.” (current directory) and “..” (parent directory).

Representing a Path

NSString represents paths generically with ‘/’ as the path separator and ‘.’ as the extension separator. Methods that accept strings as path arguments convert these generic representations to the proper system-specific form as needed. On systems with an implicit root directory, absolute paths begin with a path separator or with a tilde expression (“~/...” or “~user/...”). Where a device must be specified, you can do that yourself—introducing a system dependency—or allow the string object to add a default device.

You can create a standardized representation of a path using stringByStandardizingPath. This performs a number of tasks including:

for example:

NSString *path = @"/usr/bin/./grep";
NSString *standardizedPath = [path stringByStandardizingPath];
// standardizedPath: /usr/bin/grep
 
path = @"~me";
standardizedPath = [path stringByStandardizingPath];
// standardizedPath (assuming conventional naming scheme): /Users/Me
 
path = @"/usr/include/objc/..";
standardizedPath = [path stringByStandardizingPath];
// standardizedPath: /usr/include
 
path = @"/private/usr/include";
standardizedPath = [path stringByStandardizingPath];
// standardizedPath: /usr/include

User Directories

The following examples illustrate how you can use NSString’s path utilities and other Cocoa functions to get the user directories.

// Assuming that users’ home directories are stored in /Users
 
NSString *meHome = [@"~me" stringByExpandingTildeInPath];
// meHome = @"/Users/me"
 
NSString *mePublic = [@"~me/Public" stringByExpandingTildeInPath];
// mePublic = @"/Users/me/Public"

You can find the home directory for the current user and for a given user with NSHomeDirectory and NSHomeDirectoryForUser respectively:

NSString *currentUserHomeDirectory = NSHomeDirectory();
NSString *meHomeDirectory = NSHomeDirectoryForUser(@"me");

Note that you should typically use the function NSSearchPathForDirectoriesInDomains to locate standard directories for the current user. For example, instead of:

NSString *documentsDirectory =
                [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"];

you should use:

NSString *documentsDirectory;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
if ([paths count] > 0) {
    documentsDirectory = [paths objectAtIndex:0];
}

Path Components

NSString provides a rich set of methods for manipulating strings as file-system paths, for example:

pathExtensionInterprets the receiver as a path and returns the receiver’s extension, if any.
stringByDeletingPathExtensionReturns a new string made by deleting the extension (if any, and only the last) from the receiver.
stringByDeletingLastPathComponentReturns a new string made by deleting the last path component from the receiver, along with any final path separator.

Using these and related methods described in NSString Class Reference, you can extract a path’s directory, filename, and extension, as illustrated by the following examples.

NSString *documentPath = @"~me/Public/Demo/readme.txt";
 
NSString *documentDirectory = [documentPath stringByDeletingLastPathComponent];
// documentDirectory = @"~me/Public/Demo"
 
NSString *documentFilename = [documentPath lastPathComponent];
// documentFilename = @"readme.txt"
 
NSString *documentExtension = [documentPath pathExtension];
// documentExtension = @"txt"

File Name Completion

You can find possible expansions of file names using completePathIntoString:caseSensitive:matchesIntoArray:filterTypes:. For example, given a directory ~/Demo that contains the following files:

ReadMe.txt readme.html readme.rtf recondite.txt test.txt

you can find all possible completions for the path ~/Demo/r as follows:

NSString *partialPath = @"~/Demo/r";
NSString *longestCompletion;
NSArray *outputArray;
 
unsigned allMatches = [partialPath completePathIntoString:&longestCompletion
    caseSensitive:NO
    matchesIntoArray:&outputArray
    filterTypes:NULL];
 
// allMatches = 3
// longestCompletion = @"~/Demo/re"
// outputArray = (@"~/Demo/readme.html", "~/Demo/readme.rtf", "~/Demo/recondite.txt")

You can find possible completions for the path ~/Demo/r that have an extension “.txt” or “.rtf” as follows:

NSArray *filterTypes = @[@"txt", @"rtf"];
 
unsigned textMatches = [partialPath completePathIntoString:&outputName
    caseSensitive:NO
    matchesIntoArray:&outputArray
    filterTypes:filterTypes];
// allMatches = 2
// longestCompletion = @"~/Demo/re"
// outputArray = (@"~/Demo/readme.rtf", @"~/Demo/recondite.txt")