Getting list of files in documents folder

i0S Swift Issue

Question or problem with Swift language programming:

What is wrong with my code for getting the filenames in the document folder?

func listFilesFromDocumentsFolder() -> [NSString]?{
    var theError = NSErrorPointer()
    let dirs = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.AllDomainsMask, true) as? [String]
    if dirs != nil {
        let dir = dirs![0] as NSString
        let fileList = NSFileManager.defaultManager().contentsOfDirectoryAtPath(dir, error: theError) as [NSString]
        return fileList
    }else{
        return nil
    }
}

I thought I read the documents correctly and I am very sure about what is in the documents folder, but “fileList” does not show anything? “dir” shows the path to the folder.

How to solve the problem:

Solution 1:

This solution works with Swift 4 (Xcode 9.2) and also with Swift 5 (Xcode 10.2.1+):

let fileManager = FileManager.default
let documentsURL = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0]
do {
    let fileURLs = try fileManager.contentsOfDirectory(at: documentsURL, includingPropertiesForKeys: nil)
    // process files
} catch {
    print("Error while enumerating files \(documentsURL.path): \(error.localizedDescription)")
}

Here’s a reusable FileManager extension that also lets you skip or include hidden files in the results:

import Foundation

extension FileManager {
    func urls(for directory: FileManager.SearchPathDirectory, skipsHiddenFiles: Bool = true ) -> [URL]? {
        let documentsURL = urls(for: directory, in: .userDomainMask)[0]
        let fileURLs = try? contentsOfDirectory(at: documentsURL, includingPropertiesForKeys: nil, options: skipsHiddenFiles ? .skipsHiddenFiles : [] )
        return fileURLs
    }
}

// Usage
print(FileManager.default.urls(for: .documentDirectory) ?? "none")

Solution 2:

Swift 5

// Get the document directory url
let documentsUrl =  FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!

do {
    // Get the directory contents urls (including subfolders urls)
    let directoryContents = try FileManager.default.contentsOfDirectory(at: documentsUrl, includingPropertiesForKeys: nil)
    print(directoryContents)

    // if you want to filter the directory contents you can do like this:
    let mp3Files = directoryContents.filter{ $0.pathExtension == "mp3" }
    print("mp3 urls:",mp3Files)
    let mp3FileNames = mp3Files.map{ $0.deletingPathExtension().lastPathComponent }
    print("mp3 list:", mp3FileNames)

} catch {
    print(error)
}

Solution 3:

A shorter syntax for SWIFT 3

func listFilesFromDocumentsFolder() -> [String]?
{
    let fileMngr = FileManager.default;

    // Full path to documents directory
    let docs = fileMngr.urls(for: .documentDirectory, in: .userDomainMask)[0].path

    // List all contents of directory and return as [String] OR nil if failed
    return try? fileMngr.contentsOfDirectory(atPath:docs)
}

Usage example:

override func viewDidLoad()
{
    print(listFilesFromDocumentsFolder())
}

Tested on xCode 8.2.3 for iPhone 7 with iOS 10.2 & iPad with iOS 9.3

Solution 4:

Apple states about NSSearchPathForDirectoriesInDomains(_:_:_:):


You should consider using the FileManager methods urls(for:in:) and url(for:in:appropriateFor:create:) which return URLs, which are the preferred format.


With Swift 5, FileManager has a method called contentsOfDirectory(at:includingPropertiesForKeys:options:). contentsOfDirectory(at:includingPropertiesForKeys:options:) has the following declaration:


Performs a shallow search of the specified directory and returns URLs for the contained items.

func contentsOfDirectory(at url: URL, includingPropertiesForKeys keys: [URLResourceKey]?, options mask: FileManager.DirectoryEnumerationOptions = []) throws -> [URL] 

Therefore, in order to retrieve the urls of the files contained in documents directory, you can use the following code snippet that uses FileManager‘s urls(for:in:) and contentsOfDirectory(at:includingPropertiesForKeys:options:) methods:

guard let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return } do { let directoryContents = try FileManager.default.contentsOfDirectory(at: documentsDirectory, includingPropertiesForKeys: nil, options: []) // Print the urls of the files contained in the documents directory print(directoryContents) } catch { print("Could not search for urls of files in documents directory: \(error)") } 

As an example, the UIViewController implementation below shows how to save a file from app bundle to documents directory and how to get the urls of the files saved in documents directory:

import UIKit class ViewController: UIViewController { @IBAction func copyFile(_ sender: UIButton) { // Get file url guard let fileUrl = Bundle.main.url(forResource: "Movie", withExtension: "mov") else { return } // Create a destination url in document directory for file guard let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return } let documentDirectoryFileUrl = documentsDirectory.appendingPathComponent("Movie.mov") // Copy file to document directory if !FileManager.default.fileExists(atPath: documentDirectoryFileUrl.path) { do { try FileManager.default.copyItem(at: fileUrl, to: documentDirectoryFileUrl) print("Copy item succeeded") } catch { print("Could not copy file: \(error)") } } } @IBAction func displayUrls(_ sender: UIButton) { guard let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return } do { let directoryContents = try FileManager.default.contentsOfDirectory(at: documentsDirectory, includingPropertiesForKeys: nil, options: []) // Print the urls of the files contained in the documents directory print(directoryContents) // may print [] or [file:///private/var/mobile/Containers/Data/Application/.../Documents/Movie.mov] } catch { print("Could not search for urls of files in documents directory: \(error)") } } } 

Solution 5:

This code prints out all the directories and files in my documents directory:

Some modification of your function:

func listFilesFromDocumentsFolder() -> [String] { let dirs = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.allDomainsMask, true) if dirs != [] { let dir = dirs[0] let fileList = try! FileManager.default.contentsOfDirectory(atPath: dir) return fileList }else{ let fileList = [""] return fileList } } 

Which gets called by:

 let fileManager:FileManager = FileManager.default let fileList = listFilesFromDocumentsFolder() let count = fileList.count for i in 0..

Hope this helps!