Obtenir la liste des fichiers dans le dossier des documents

124

Quel est le problème avec mon code pour obtenir les noms de fichiers dans le dossier du document?

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

Je pensais avoir lu les documents correctement et je suis très sûr de ce qu'il y a dans le dossier des documents, mais "fileList" ne montre rien? "dir" montre le chemin du dossier.

pawi
la source
vous voulez afficher les noms des fichiers qui se trouvent dans le répertoire des documents ou les fichiers qui se trouvent également dans les dossiers?
Adeel Ur Rehman
d'abord, seuls les fichiers dans le dossier du document lui-même!
pawi
J'ai juste exécuté votre code et cela a fonctionné comme prévu. J'ai une liste de ce qui se trouve dans mon répertoire de documents. Avons-nous mal compris votre question?
jwlaughton
Étrange? J'ai également utilisé ".fileExistsAtPath (chemin)" qui m'indique qu'un fichier spécifique est présent. Mais rien n'apparaît dans "fileList" !?
pawi
Ma liste comprenait à la fois des répertoires et des fichiers.
jwlaughton

Réponses:

111

Cette solution fonctionne avec Swift 4 (Xcode 9.2) et également avec 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)")
}

Voici une extension FileManager réutilisable qui vous permet également d'ignorer ou d'inclure des fichiers cachés dans les résultats:

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")
Karoly Nyisztor
la source
Comment puis-je exclure des fichiers cachés?
BasedMusa
251

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)
}
Leo Dabus
la source
1
Pour les gens aussi insouciants que moi. Notez que l'appel: FileManager.default.contentsOfDirectory (atPath: <# T ## String #>) peut ne pas fonctionner correctement pour des raisons inconnues dans Swift 3.0. Utilisez celui donné ci-dessus ici.
Michael Shang
Si je l'exécute sur un répertoire iCloud Drive, il ne renvoie que les éléments qui ont été téléchargés sur l'appareil - existe-t-il un moyen d'obtenir les URL de tous les éléments sans les télécharger au préalable?
mralexhay le
@mralexhay cela me le montre même les éléments qui ne sont pas téléchargés. Il doit afficher un .préfixe de point et un .cloudsuffixe dans le nom du fichier. essayez let icloudFiles = directoryContents.filter{ $0.pathExtension == "icloud" }il devrait afficher les fichiers qui ne sont pas téléchargés
Leo Dabus
1
@LeoDabus merci pour la réponse - je n'avais pas réalisé qu'il ajoute le ".", Je pensais qu'il avait juste le suffixe "iCloud". J'ai réalisé que je ne retournais pas de fichiers cachés - pas étonnant qu'ils ne s'affichent pas! Merci encore.
mralexhay le
17

Une syntaxe plus courte pour 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)
}

Exemple d'utilisation:

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

Testé sur xCode 8.2.3 pour iPhone 7 avec iOS 10.2 et iPad avec iOS 9.3

Nikita Kurtin
la source
6

Apple déclare à propos de NSSearchPathForDirectoriesInDomains(_:_:_:):

Vous devriez envisager d'utiliser les FileManagerméthodes urls(for:in:)et les url(for:in:appropriateFor:create:)URL de retour, qui sont le format préféré.


Avec Swift 5, FileManagera une méthode appelée contentsOfDirectory(at:includingPropertiesForKeys:options:). contentsOfDirectory(at:includingPropertiesForKeys:options:)a la déclaration suivante:

Effectue une recherche superficielle dans le répertoire spécifié et renvoie les URL des éléments contenus.

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

Par conséquent, afin de récupérer les URL des fichiers contenus dans le répertoire documents, vous pouvez utiliser l'extrait de code suivant qui utilise FileManager les méthodes urls(for:in:)et contentsOfDirectory(at:includingPropertiesForKeys:options:):

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

À titre d'exemple, l' UIViewControllerimplémentation ci-dessous montre comment enregistrer un fichier du bundle d'applications dans le répertoire documents et comment obtenir les URL des fichiers enregistrés dans le répertoire documents:

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

}
Imanou Petit
la source
5

Ce code imprime tous les répertoires et fichiers de mon répertoire de documents:

Quelques modifications de votre fonction:

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

Qui est appelé par:

    let fileManager:FileManager = FileManager.default
    let fileList = listFilesFromDocumentsFolder()

    let count = fileList.count

    for i in 0..<count
    {
        if fileManager.fileExists(atPath: fileList[i]) != true
        {
            print("File is \(fileList[i])")
        }
    }
jwlaughton
la source
4

Compatibilité Swift 2.0

func listWithFilter () {

    let fileManager = NSFileManager.defaultManager()
           // We need just to get the documents folder url
    let documentsUrl = fileManager.URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0] as NSURL

    do {
    // if you want to filter the directory contents you can do like this:
    if let directoryUrls = try? NSFileManager.defaultManager().contentsOfDirectoryAtURL(documentsUrl, includingPropertiesForKeys: nil, options: NSDirectoryEnumerationOptions.SkipsSubdirectoryDescendants) {
        print(directoryUrls)
       ........
        }

    }

}

OU

 func listFiles() -> [String] {

    var theError = NSErrorPointer()
    let dirs = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.AllDomainsMask, true) as? [String]
    if dirs != nil {
        let dir = dirs![0]
        do {
        let fileList = try NSFileManager.defaultManager().contentsOfDirectoryAtPath(dir)
        return fileList as [String]
        }catch {

        }

    }else{
        let fileList = [""]
        return fileList
    }
    let fileList = [""]
    return fileList

}
Gleb
la source
0

Solution simple et dynamique (Swift 5):

extension FileManager {

  class func directoryUrl() -> URL? {
      let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
      return paths.first
  }

  class func allRecordedData() -> [URL]? {
     if let documentsUrl = FileManager.directoryUrl() {
        do {
            let directoryContents = try FileManager.default.contentsOfDirectory(at: documentsUrl, includingPropertiesForKeys: nil)
            return directoryContents.filter{ $0.pathExtension == "m4a" }
        } catch {
            return nil
        }
     }
     return nil
  }}
nitin.agam
la source