Ottenere l'elenco dei file nella cartella dei documenti


124

Cosa c'è di sbagliato nel mio codice per ottenere i nomi dei file nella cartella dei documenti?

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

Pensavo di aver letto correttamente i documenti e sono molto sicuro di cosa c'è nella cartella dei documenti, ma "fileList" non mostra nulla? "dir" mostra il percorso della cartella.


vuoi mostrare i nomi dei file che si trovano nella directory dei documenti o anche i file che sono nelle cartelle?
Adeel Ur Rehman

in primo luogo, solo i file nella cartella dei documenti stessa!
pawi

Ho appena eseguito il tuo codice e ha funzionato come previsto. Ho un elenco di ciò che è nella mia directory dei documenti. Non comprendiamo la tua domanda?
jwlaughton

Strano? ho anche usato ".fileExistsAtPath (path)" che mi dice che è presente un file specifico. Ma non compare nulla in "fileList" !?
pawi

Il mio elenco includeva sia directory che file.
jwlaughton

Risposte:


111

Questa soluzione funziona con Swift 4 (Xcode 9.2) e anche con 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)")
}

Ecco un'estensione FileManager riutilizzabile che ti consente anche di saltare o includere file nascosti nei risultati:

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

Come posso escludere i file nascosti?
Basato su Musa

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

1
Per le persone che sono sbadate come me. Tieni presente che la chiamata: FileManager.default.contentsOfDirectory (atPath: <# T ## String #>) potrebbe non funzionare correttamente per motivi sconosciuti in Swift 3.0. Usa quello qui sopra.
Michael Shang

Se lo eseguo su una directory di iCloud Drive, restituisce solo gli elementi che sono stati scaricati sul dispositivo: esiste un modo per ottenere gli URL di tutti gli elementi senza scaricarli prima?
mralexhay

@mralexhay me lo mostra anche gli elementi che non vengono scaricati. Dovrebbe mostrare un .prefisso punto e un .cloudsuffisso nel nome del file. provalo let icloudFiles = directoryContents.filter{ $0.pathExtension == "icloud" }dovrebbe mostrare i file che non vengono scaricati
Leo Dabus

1
@LeoDabus grazie per la risposta - non mi ero reso conto che antepone il ".", Pensavo avesse solo il suffisso "iCloud". Mi sono reso conto che non stavo restituendo file nascosti - non c'è da stupirsi che non siano stati visualizzati! Grazie ancora.
mralexhay

17

Una sintassi più breve per 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)
}

Esempio di utilizzo:

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

Testato su xCode 8.2.3 per iPhone 7 con iOS 10.2 e iPad con iOS 9.3


6

Apple afferma di NSSearchPathForDirectoriesInDomains(_:_:_:):

Dovresti considerare l'utilizzo dei FileManagermetodi urls(for:in:)e degli url(for:in:appropriateFor:create:)URL di ritorno, che sono il formato preferito.


Con Swift 5, FileManagerha un metodo chiamato contentsOfDirectory(at:includingPropertiesForKeys:options:). contentsOfDirectory(at:includingPropertiesForKeys:options:)ha la seguente dichiarazione:

Esegue una ricerca superficiale nella directory specificata e restituisce gli URL per gli elementi contenuti.

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

Pertanto, per recuperare gli URL dei file contenuti nella directory dei documenti, è possibile utilizzare il seguente frammento di codice che utilizza FileManageri metodi urls(for:in:)e 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)")
}

Ad esempio, l' UIViewControllerimplementazione di seguito mostra come salvare un file dall'app bundle nella directory dei documenti e come ottenere gli URL dei file salvati nella directory dei documenti:

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

}

5

Questo codice stampa tutte le directory e i file nella directory dei miei documenti:

Alcune modifiche alla tua funzione:

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

Che viene chiamato da:

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

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

    }

}

O

 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

}

0

Soluzione semplice e dinamica (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
  }}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.