I have a NSURL object. It has address of a filesystem element, it is either a file or a directory. I want to be able to tell if the NSURL is a directory or a file.
I have already tried this, which doesn"t seem to work!
NSURL * temp ....... ;// it is initialized and has a valid value
CFURLRef xx = (CFURLRef)CFBridgingRetain(temp);
if(CFURLHasDirectoryPath(xx)) NSLog(@"was a file");
else NSLog(@"was a folder");
NSNumber *isDirectory;
// this method allows us to get more information about an URL.
// We're passing NSURLIsDirectoryKey as key because that's the info we want to know.
// Also, we pass a reference to isDirectory variable, so it can be modified to have the return value
BOOL success = [url getResourceValue:&isDirectory forKey:NSURLIsDirectoryKey error:nil];
// If we could read the information and it's indeed a directory
if (success && [isDirectory boolValue]) {
NSLog(@"Congratulations, it's a directory!");
} else {
NSLog(@"It seems it's just a file.");
}
With Swift 5, you can check if a URL path represents a directory or a regular file using one of the following macOS Playground sample codes.
#1. Using URL
's hasDirectoryPath
property
import Foundation
let url = URL(fileURLWithPath: "/Users/User/Desktop")
print("is directory:", url.hasDirectoryPath)
#2. Using Filemanager
's attributesOfItem(atPath:)
method
import Foundation
let url = URL(fileURLWithPath: "/Users/User/Desktop/File.pdf")
let attributes = try! FileManager.default.attributesOfItem(atPath: url.path)
if let type = attributes[FileAttributeKey.type] as? FileAttributeType {
print("is file:", type == FileAttributeType.typeRegular)
}
import Foundation
let url = URL(fileURLWithPath: "/Users/User/Desktop")
let attributes = try! FileManager.default.attributesOfItem(atPath: url.path)
if let type = attributes[FileAttributeKey.type] as? FileAttributeType {
print("is directory:", type == FileAttributeType.typeDirectory)
}
#3. Using URLResourceValues
import Foundation
let url = URL(fileURLWithPath: "/Users/User/Desktop")
if let resources = try? url.resourceValues(forKeys: [.isDirectoryKey]) {
let isDirectory = resources.isDirectory ?? false
print(isDirectory)
} else {
print("No such file or directory")
}
import Foundation
let url = URL(fileURLWithPath: "/Users/User/Desktop/File.pdf")
if let resources = try? url.resourceValues(forKeys: [.isRegularFileKey]) {
let isFile = resources.isRegularFile ?? false
print(isFile)
} else {
print("No such file or directory")
}
#4. Using FileManager
's fileExists(atPath:isDirectory:)
import Foundation
let url = URL(fileURLWithPath: "/Users/User/Desktop")
var isDirectory: ObjCBool = false
let fileExists = FileManager.default.fileExists(atPath: url.path, isDirectory: &isDirectory)
print("is directory:", fileExists && isDirectory.boolValue)
Starting [iOS 9, macOS 10.11, tvOS 9.0, watchOS 2.0], there is hasDirectoryPath
:
url.hasDirectoryPath
If you know the file URL has been standardized, then you can test for a trailing slash.
-URLByStandardizingPath
will standardize a file URL including ensuring a trailing slash if the path is a directory.
Here is a test which shows -URLByStandardizingPath
adding the trailing slash:
// Get a directory, any directory will do
NSURL *initialURL = [[NSBundle mainBundle] bundleURL];
NSString *initialString = [initialURL absoluteString];
// String the trailing slash off the directory
NSString *directoryString = [initialString substringToIndex:[initialString length] - 1];
NSURL *directoryURL = [NSURL URLWithString:directoryString];
XCTAssertFalse([[directoryURL absoluteString] hasSuffix:@"/"],
@"directoryURL should not end with a slash");
XCTAssertTrue([[[directoryURL URLByStandardizingPath] absoluteString] hasSuffix:@"/"],
@"[directoryURL URLByStandardizingPath] should end with a slash");
As you can see, [[[directoryURL URLByStandardizingPath] absoluteString] hasSuffix:@"/"]
is the test.
Starting iOS 8, in Swift 3, there is isDirectory
:
(try? url.resourceValues(forKeys: [.isDirectoryKey]))?.isDirectory ?? false