使用Swift';遍历文件夹及其子文件夹中的文件;s文件管理器

使用Swift';遍历文件夹及其子文件夹中的文件;s文件管理器,swift,cocoa,nsfilemanager,Swift,Cocoa,Nsfilemanager,我对编写Swift非常陌生,我正在尝试遍历文件夹中的文件。 我看了一下答案,试图将其翻译成快速语法,但没有成功 let fileManager = NSFileManager.defaultManager() let enumerator:NSDirectoryEnumerator = fileManager.enumeratorAtPath(folderPath) for element in enumerator { //do something } 我得到的错误是: Type

我对编写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'
我的目标是查看主文件夹中包含的所有子文件夹和文件,找到具有特定扩展名的所有文件,然后对它们进行处理。

使用枚举器的方法。:

while let element = enumerator?.nextObject() as? String {
    if element.hasSuffix("ext") { // checks the extension
    }
}

我根本无法让pNre的解决方案发挥作用;while循环从未收到任何东西。然而,我确实遇到了这个适合我的解决方案(在Xcode 6 beta 6中,所以自从pNre发布了上述答案后,情况可能发生了变化?)


以防你得到

'NSDirectoryEnumerator?没有名为'nextObject'的成员。错误

while循环应该是:

while let element = enumerator?.nextObject() as? String {
  // do things with element
}
它与更新Swift 3有关:

let fileManager = FileManager()     // let fileManager = NSFileManager.defaultManager()
let en=fileManager.enumerator(atPath: the_path)   // let enumerator:NSDirectoryEnumerator = fileManager.enumeratorAtPath(folderPath)

while let element = en?.nextObject() as? String {
    if element.hasSuffix("ext") {
        // do something with the_path/*.ext ....
    }
}
斯威夫特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)
    }
})
Swift3+绝对URL
基于SWIFT 3.0中的代码

返回传递的目录及其子目录中具有扩展名的所有文件

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
}
import Foundation

let path = "<some path>"

let enumerator = FileManager.default.enumerator(atPath: path)

while let filename = enumerator?.nextObject() as? String {
        print(filename)
}
如今(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)
}

返回目录+子目录中的所有文件

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
}
import Foundation

let path = "<some path>"

let enumerator = FileManager.default.enumerator(atPath: path)

while let filename = enumerator?.nextObject() as? String {
        print(filename)
}
<代码>导入基础 let path=“” 让enumerator=FileManager.default.enumerator(atPath:path) 而让filename=enumerator?.nextObject()作为?串{ 打印(文件名) }
如果要分类检查元素是文件还是子目录:

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
    }
}

除了瓦迪安的回应之外,苹果文档提到基于路径的URL在某些方面更简单,但是文件引用URL的优点是,如果在应用程序运行时移动或重命名文件,则引用仍然有效

从“访问文件和目录”的文档中:

“基于路径的URL更易于操作,更易于调试,并且通常是NSFileManager等类的首选。文件引用URL的一个优点是,在应用程序运行时,它们比基于路径的URL更脆弱。如果用户在Finder中移动文件,则引用该文件的任何基于路径的URL立即无效,必须更新为新路径。但是,只要文件移动到同一磁盘上的另一个位置,其唯一ID不会更改,任何文件引用URL都保持有效。”


最近在处理URL数组时遇到了这个问题,不管它们是否是目录(例如拖放)。最后在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
    }
}

避免使用引用URL,尽管它们确实具有上述一些优点,但它们会消耗系统资源,如果您正在枚举一个大文件系统(实际上没有那么大),您的应用程序将很快撞上系统墙,并被macOS关闭。

我的两分钱来自以前的anwers..更快捷,并且具有可选功能:

 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")
            }
        }

    }


根据用户1398498下面的回答,如果没有可选的链接,就无法实现此功能。刚刚尝试了此功能,我只得到了一个无限循环,不得不大致采用Rainier的方法。非常奇怪的是,一个相当粗糙的
while
比密集的
for
解决方案更受欢迎。(哦,我看到我已经对另一个解决方案做了类似的评论-无论如何)对于那些使用
枚举器(at:,includingPropertiesForKeys:,options:)
的人来说,考虑到元素实际上是一个URL而不是字符串,所以如果使用该代码,它将不返回任何内容。
而让元素=枚举器?.nextObject()作为?URL{…}
很好的参考资料。我也从下面的链接中找到了它。有趣的是,这个解决方案的up投票数太少,因为它的语法比当前最常用的要简单得多。之所以有投票数,是因为它依赖于强制展开枚举数(枚举数!)与enumerator相反?在最上面的投票答案中。注意这是无法使用的大目录-它可能会挂起几分钟。停止强制展开。当我使用此代码时,我发现路径中带有空格的目录/文件被忽略。知道为什么会发生这种情况吗?然后我尝试了@vadian的代码,它会按预期工作。它不会进入子目录,也不会被删除隐藏文件或遵循符号链接显示我们得到的是完整路径而不是文件名吗?您使用的是哪种路径?在我的例子中,我在xcode项目中有“mydir”目录。当我使用
let path=“mydir”时“
,什么也没发生。我正在使用swift 5。这是一个完整的路径。有没有办法使用相对路径,以便将其包含在项目文件夹中?谢谢您的详细介绍。(对于路径类型的版本,我一点运气都没有,因为myURL.absolutePath对于NSFileEnumerator来说不是有效的基于字符串的路径,并且没有创建有效的枚举器)。对于URLResourceKeys列表,请看这是一个很好的示例,说明了如何执行深度搜索,对我来说非常有用。感谢您的出色贡献。此代码非常有用。但我想了解遍历根文件夹中至少第一个子目录中的文件的进度(当然,我知道,在列举所有文件之前,我们无法获得确切的文件总数。因此,最好了解“至少第一个子级别”的获取进度。)。有什么方法可以取得进展吗?没有回答问题,这应该是一个评论而不是答案。这是这里最有用的条目,因为它突出显示了按目录和文件类型来区分条目。这似乎是类似于此功能中被遗忘的一部分。