Iterate through files in a folder and its subfolders using Swift’s FileManager

i0S Swift Issue

Question or problem with Swift language programming:

I’m quite new to programming a Swift and I’m trying to iterate through the files in a folder.
I took a look at the answer here and tried to translate it to Swift syntax, but didn’t succeed.

let fileManager = NSFileManager.defaultManager()
let enumerator:NSDirectoryEnumerator = fileManager.enumeratorAtPath(folderPath)

for element in enumerator {
    //do something
}

the error I get is:

Type 'NSDirectoryEnumerator' does not conform to protocol 'SequenceType'

My aim is to look at all the subfolders and files contained into the main folder and find all the files with a certain extension to then do something with them.

How to solve the problem:

Solution 1:

Use the nextObject() method of enumerator:

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

Solution 2:

Nowadays (early 2017) it’s highly recommended to use the – more versatile – URL related 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)
}

Solution 3:

I couldn’t get pNre’s solution to work at all; the while loop just never received anything. However, I did come across this solution which works for me (in Xcode 6 beta 6, so perhaps things have changed since pNre posted the above answer?):

for url in enumerator!.allObjects {
    print("\((url as! NSURL).path!)")
}

Solution 4:

returns all files in a directory + in subdirectories

import Foundation

let path = ""

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

while let filename = enumerator?.nextObject() as? String {
        print(filename)
}

Solution 5:

Swift3 + absolute urls

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

Based on code from @user3441734

Hope this helps!