我对编写Swift非常陌生,我试图遍历文件夹中的文件。 我看了一下答案here并尝试将其翻译成Swift语法,但没有成功。
let fileManager = NSFileManager.defaultManager()
let enumerator:NSDirectoryEnumerator = fileManager.enumeratorAtPath(folderPath)
for element in enumerator {
//do something
}
我得到的错误是:
Type 'NSDirectoryEnumerator' does not conform to protocol 'SequenceType'
我的目的是查看主文件夹中包含的所有子文件夹和文件,找到具有特定扩展名的所有文件,然后对它们执行某些操作。
答案 0 :(得分:72)
使用enumerator
的{{3}}方法:
while let element = enumerator?.nextObject() as? String {
if element.hasSuffix("ext") { // checks the extension
}
}
答案 1 :(得分:50)
如今(2017年初),强烈建议使用 - 更通用的 - 与URL相关的API
let fileManager = FileManager.default
do {
let resourceKeys : [URLResourceKey] = [.creationDateKey, .isDirectoryKey]
let documentsURL = try fileManager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
let enumerator = FileManager.default.enumerator(at: documentsURL,
includingPropertiesForKeys: resourceKeys,
options: [.skipsHiddenFiles], errorHandler: { (url, error) -> Bool in
print("directoryEnumerator error at \(url): ", error)
return true
})!
for case let fileURL as URL in enumerator {
let resourceValues = try fileURL.resourceValues(forKeys: Set(resourceKeys))
print(fileURL.path, resourceValues.creationDate!, resourceValues.isDirectory!)
}
} catch {
print(error)
}
答案 2 :(得分:18)
我根本无法获得pNre的解决方案。 while循环从未收到任何东西。但是,我确实遇到过这个适用于我的解决方案(在Xcode 6 beta 6中,所以自从pNre发布上述答案以来,情况可能已经发生了变化?):
for url in enumerator!.allObjects {
print("\((url as! NSURL).path!)")
}
答案 3 :(得分:5)
如果您正在获取
'NSDirectoryEnumerator?'没有名为'nextObject'的成员错误
while循环应该是:
while let element = enumerator?.nextObject() as? String {
// do things with element
}
有关
答案 4 :(得分:5)
Swift 3
let fd = FileManager.default
fd.enumerator(atPath: "/Library/FileSystems")?.forEach({ (e) in
if let e = e as? String, let url = URL(string: e) {
print(url.pathExtension)
}
})
答案 5 :(得分:5)
返回目录中的所有文件+子目录
import Foundation
let path = "<some path>"
let enumerator = FileManager.default.enumerator(atPath: path)
while let filename = enumerator?.nextObject() as? String {
print(filename)
}
答案 6 :(得分:4)
SWIFT 3.0
返回目录中传递的所有带扩展名的文件&amp;它的子目录
func extractAllFile(atPath path: String, withExtension fileExtension:String) -> [String] {
let pathURL = NSURL(fileURLWithPath: path, isDirectory: true)
var allFiles: [String] = []
let fileManager = FileManager.default
let pathString = path.replacingOccurrences(of: "file:", with: "")
if let enumerator = fileManager.enumerator(atPath: pathString) {
for file in enumerator {
if #available(iOS 9.0, *) {
if let path = NSURL(fileURLWithPath: file as! String, relativeTo: pathURL as URL).path, path.hasSuffix(".\(fileExtension)"){
let fileNameArray = (path as NSString).lastPathComponent.components(separatedBy: ".")
allFiles.append(fileNameArray.first!)
}
} else {
// Fallback on earlier versions
print("Not available, #available iOS 9.0 & above")
}
}
}
return allFiles
}
答案 7 :(得分:3)
extension FileManager {
func listFiles(path: String) -> [URL] {
let baseurl: URL = URL(fileURLWithPath: path)
var urls = [URL]()
enumerator(atPath: path)?.forEach({ (e) in
guard let s = e as? String else { return }
let relativeURL = URL(fileURLWithPath: s, relativeTo: baseurl)
let url = relativeURL.absoluteURL
urls.append(url)
})
return urls
}
}
基于@ user3441734的代码
答案 8 :(得分:2)
更新Swift 3:
names(df) = filenames
答案 9 :(得分:1)
添加到vadian的响应 - Apple文档提到基于路径的URL在某些方面更简单,但文件引用URL的优势在于,如果在应用程序中移动或重命名文件,引用仍然有效正在运行。
来自&#34;访问文件和目录的文档&#34;:
&#34;基于路径的URL更易于操作,更易于调试,并且通常被NSFileManager等类所优选。文件引用URL的一个优点是,当您的应用程序运行时,它们不如基于路径的URL脆弱。如果用户在Finder中移动文件,则任何引用该文件的基于路径的URL都将立即变为无效,并且必须更新到新路径。但是,只要文件移动到同一磁盘上的另一个位置,其唯一ID就不会更改,并且任何文件引用URL仍然有效。&#34;
答案 10 :(得分:1)
我以前发给别人的两分钱。.更加快捷和可选:
let enumerator = FileManager.default.enumerator(atPath: folderPath)
while let element = enumerator?.nextObject() as? String {
print(element)
if let fType = enumerator?.fileAttributes?[FileAttributeKey.type] as? FileAttributeType{
switch fType{
case .typeRegular:
print("a file")
case .typeDirectory:
print("a dir")
}
}
}
答案 11 :(得分:0)
如果要分类检查元素是文件还是子目录:
let enumerator = FileManager.default.enumerator(atPath: contentsPath);
while let element = enumerator?.nextObject() as? String {
if(enumerator?.fileAttributes?[FileAttributeKey.type] as! FileAttributeType == FileAttributeType.typeRegular){
//this is a file
}
else if(enumerator?.fileAttributes?[FileAttributeKey.type] as! FileAttributeType == FileAttributeType.typeDirectory){
//this is a sub-directory
}
}
答案 12 :(得分:0)
最近在处理一系列网址时遇到了困难,无论它们是否是目录(例如拖放)。在swift 4中结束此扩展,可能有用
extension Sequence where Iterator.Element == URL {
var handleDir: [URL] {
var files: [URL] = []
self.forEach { u in
guard u.hasDirectoryPath else { return files.append(u.resolvingSymlinksInPath()) }
guard let dir = FileManager.default.enumerator(at: u.resolvingSymlinksInPath(), includingPropertiesForKeys: nil) else { return }
for case let url as URL in dir {
files.append(url.resolvingSymlinksInPath())
}
}
return files
}
}
答案 13 :(得分:0)
避免使用参考URL,虽然它们确实具有上述优点,但它们会占用系统资源,如果您要枚举大型文件系统(实际上并不大),您的应用程序将快速进入系统墙并被macOS关闭。
答案 14 :(得分:0)
您可以考虑的另一种方法是将枚举器(实际上是 NSEnumerator
)包装到一个 IteratorProtocol
中,例如:
private struct FilePathIterator: IteratorProtocol {
var enumerator: FileManager.DirectoryEnumerator
func next() -> String? {
enumerator.nextObject() as? String
}
}
这样做之后,您可以基于迭代器创建一个序列:
let pathsSequence = AnySequence {
FilePathIterator(
enumerator: fileManager.enumeratorAtPath(folderPath)
)
}
创建的序列非常适合for...in
:
for let path in pathsSequence {
...
}
与其他解决方案相比,该解决方案完全按照要求使用 for...in
,并且如果我们将其与 .allObjects
变体进行比较,还可以避免将所有内容加载到内存中并消耗更少的内存。