使用swift递归列出文件夹中的所有文件

ike*_*kel 8 directory recursion file swift

我正在快速学习并想知道在目录中列出所有具有绝对路径的文件的最佳方法是什么,包括来自子文件夹的文件(仅限文件)

我尝试了以下操作,但似乎列出了所有内容名称,甚至没有完整路径的文件夹名称。

let paths = FileManager.default.subpaths(atPath: folderPath)
    for p in paths! {
       print p
    }
}
Run Code Online (Sandbox Code Playgroud)

let items = try fm.contentsOfDirectory(atPath: folderPath)

谷歌搜索没有提出任何工作方法。

这适用于 macOS 10.14

任何帮助表示赞赏!

谢谢

vad*_*ian 18

FileManager 还有一种深度搜索的方法: enumerator(at:includingPropertiesForKeys:options:errorHandler:)

要仅获取文件,您必须迭代枚举器并过滤文件

let url = URL(fileURLWithPath: "/path/to/directory")
var files = [URL]()
if let enumerator = FileManager.default.enumerator(at: url, includingPropertiesForKeys: [.isRegularFileKey], options: [.skipsHiddenFiles, .skipsPackageDescendants]) {
    for case let fileURL as URL in enumerator {
        do {
            let fileAttributes = try fileURL.resourceValues(forKeys:[.isRegularFileKey])
            if fileAttributes.isRegularFile! {
                files.append(fileURL)
            }
        } catch { print(error, fileURL) }
    }
    print(files)
}
Run Code Online (Sandbox Code Playgroud)

强烈建议使用 URL 而不是字符串路径。


bso*_*ino 5

FileManager是正确的对象

如果您正在使用swift 5或以上可以利用AsyncStream。下面一个简单的Playground

import Foundation
import Combine

// Recursive iteration     
func walkDirectory(at url: URL, options: FileManager.DirectoryEnumerationOptions ) -> AsyncStream<URL> {
    AsyncStream { continuation in
        Task {
            let enumerator = FileManager.default.enumerator(at: url, includingPropertiesForKeys: nil, options: options)
                
            while let fileURL = enumerator?.nextObject() as? URL {
                if fileURL.hasDirectoryPath {
                    for await item in walkDirectory(at: fileURL, options: options) {
                        continuation.yield(item)
                    }
                } else {
                    continuation.yield( fileURL )
                }
            }
            continuation.finish()
        }
    }
}


// use it     
let path = URL( string: "<your path>" )

let options: FileManager.DirectoryEnumerationOptions = [.skipsHiddenFiles, .skipsPackageDescendants]
    
Task {
        
    let swiftFiles = walkDirectory(at: path!, options: options).filter {
        $0.pathExtension == "swift"
    }

    for await item in swiftFiles {
        print(item.lastPathComponent)
    }
        
}

Run Code Online (Sandbox Code Playgroud)