This article describes how to create URLs and strings that represent paths, and how to locate standard directories in the filesystem.
NSString
provides a number of path-utility methods that you can use to, for example, extract the components of a path (the directory, filename, and extension), create paths from those components, “translate” path separators, clean up paths containing symbolic links and redundant slashes, and perform similar tasks.
In Mac OS X v10.6 and later, NSURL
provides a number of path-utility methods analogous to those provided by NSString
. Where possible, you should typically use URL-based method rather than string-based methods, since the URL-based operations are usually much more efficient than the string-based equivalents. Rather than manipulating paths as strings, therefore, where possible you should use NSURL
objects directly.
Whether you use NSString
or NSURL
, whenever you need to perform any operation on a path, you should use these methods rather than any other approach.
Absolute and Relative Paths: An absolute pathname starts with the root directory of the file system, represented by a slash (/), and ends with the file or directory that the pathname identifies. A relative pathname is relative to the current directory, the directory in which you are working and in which saved files are currently stored (if no pathname is specified). Relative pathnames start with a subdirectory of the current directory—without an initial slash—and end with the name of the file or directory the pathname identifies.
In Mac OS X v10.6 and later, you should typically use NSURL
-based APIs to perform file-related operations. The following code fragment shows how, given a URL that contains a file path, you can determine the filename and path extension, remove the filename to determine the directory that contains the file, and create a new file URL in which the original file name is prepended by “Copy of”. (For example, if the original path were /Users/me/MyFile.txt
, the new path would be /Users/me/Copy of MyFile.txt
.)
NSURL *url = <#URL containing a file path#>; |
NSString *extension = [url pathExtension]; |
NSString *fileName = [[url lastPathComponent] stringByDeletingPathExtension]; |
NSString *copyFileName = [@"Copy of " stringByAppendingString:fileName]; |
NSURL *copyURL = [url URLByDeletingLastPathComponent]; |
copyURL = [copyURL URLByAppendingPathComponent:copyFileName]; |
copyURL = [copyURL URLByAppendingPathExtension:extension]; |
(To create a copy of a file in the same way that Finder does, see “Moving Files to the Trash.”)
The following code fragment shows how, given a string that contains a file path, you can determine the filename and path extension, remove the filename to determine the directory that contains the file, and create a new path in which the original file name is prepended by “Copy of”. (For example, if the original path were /Users/me/MyFile.txt
, the new path would be /Users/me/Copy of MyFile.txt
.)
NSString *path = <#String containing a file path#>; |
NSString *extension = [path pathExtension]; |
NSString *fileName = [[path lastPathComponent] stringByDeletingPathExtension]; |
NSString *copyFileName = [@"Copy of " stringByAppendingString:fileName]; |
NSString *copyPath = [path stringByDeletingLastPathComponent]; |
copyPath = [copyPath stringByAppendingPathComponent:copyFileName]; |
copyPath = [copyPath stringByAppendingPathExtension:extension]; |
(To create a copy of a file in the same way that Finder does, see “Duplicating Files.”)
Mac OS X and iOS define a number of standard directories—for example directories to contain a user’s documents or system frameworks. Obviously the location of some of these directories—such as the user’s documents directory—is not fixed (it depends on the current user), however, in general you should not rely on other directories, such as the system frameworks directory, remaining in the same location across different versions of the operating system. Rather than hard-coding directory paths, therefore you should use one of the functions or methods that help you to locate standard directories in the file system.
Cocoa provides the following functions that return path strings for a few standard directories directly:
NSHomeDirectory | Returns the path to the current user’s home directory. |
NSHomeDirectoryForUser | Returns the path to a given user’s home directory. |
NSTemporaryDirectory | Returns the path of the temporary directory for the current user. |
You can use the returned values in conjunction with NSString
path utility methods to create other paths, for example:
NSString *path = [NSHomeDirectory() stringByAppendingPathComponent:@"MyFile.txt"]; |
For other standard directories, you use the NSSearchPathForDirectoriesInDomains
function (which returns paths as NSString
objects) or—in Mac OS X v10.6 and later—the URLsForDirectory:inDomains:
and URLForDirectory:inDomain:appropriateForURL:create:error:
methods of NSFileManager
(which return URLs). The function and the methods use constants to identify the directory—or directories—you’re interested in. There are two types of constant:
Constants in the NSSearchPathDirectory
enumeration that identify the name or type of directory (for example, Library
, Documents
, or Applications
); such as, NSDocumentDirectory
, NSDesktopDirectory
, and NSLibraryDirectory
.
Bitmask constants in the NSSearchPathDomainMask
enumeration that identify the file-system domain (User, System, Local, Network) or all domains; such as, NSUserDomainMask
and NSLocalDomainMask
.
In general, NSSearchPathForDirectoriesInDomains
and URLsForDirectory:inDomains:
may return multiple values if the parameters imply multiple locations. However, you should not make any assumptions as to the number of paths returned. Some domains or locations might be made obsolete over time, or other new domains or locations might be added (while preserving the older ones); in either case, the number of paths in the returned array might increase or decrease. Simply look at all of the returned values if you want to enumerate all of the files, or, if you just want to copy or move a file to a location and multiple paths are returned, use the first one in the array.
In Mac OS X v10.6 and later, you can use an NSFileManager
object to locate standard system directories. Its methods return NSURL
objects rather than string-based paths.
URLsForDirectory:inDomains:
is analogous to NSSearchPathForDirectoriesInDomains
. You specify the type of directory and the domain you want to find and the method returns an array of URLs. The following example illustrates how you can use the method to get a URL for the current user’s Documents directory:
NSFileManager *fileManager = [NSFileManager defaultManager]; |
NSArray *urls = [fileManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask]; |
if ([paths count] > 0) { |
NURL *userDocumentsURL = [urls objectAtIndex:0]; |
// Implementation continues... |
URLsForDirectory:inDomains:
simply returns a URL for the appropriate directory; it does not guarantee that the directory exists. If you want to perform operations such as writing to the directory, you may have to create it first.
URLForDirectory:inDomain:appropriateForURL:create:error:
is a URL-based replacement for FSFindFolder
. You can specify and optionally create a directory for a particular purpose (for example, the replacement of a particular item on disk, or a particular Library directory). You may pass only one of the values from the NSSearchPathDomainMask
enumeration, and you may not pass NSAllDomainsMask
.
The following example illustrates how you can use the NSSearchPathForDirectoriesInDomains
function to find the current user’s Documents directory:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); |
if ([paths count] > 0) { |
NSString *userDocumentsPath = [paths objectAtIndex:0]; |
// Implementation continues... |
NSSearchPathForDirectoriesInDomains
simply returns the path of the appropriate directory, it does not guarantee that the directory exists. If you want to perform operations such as writing to the directory, you may have to create it first.
Constructing a pathname to a file does not guarantee that the file exists at that path. Specifying a path results in one of the following possibilities:
A file exists at that path.
A link to a file exists at that path.
A broken link exists at that path.
No file exists at that path.
If the pathname specifies a valid file or link, you can obtain information about the file using the NSFileManager
method attributesOfItemAtPath:error:
(see “Getting and Setting File Attributes”). This method does not traverse a link however. You can first call destinationOfSymbolicLinkAtPath:error:
and then attributesOfItemAtPath:error:
. In Mac OS X v10.6 and later, you can use NSURL
methods URLByResolvingSymlinksInPath
and resourceValuesForKeys:error:
(see “Getting and Setting File Attributes”).
Last updated: 2009-07-31