Mendapatkan daftar file di folder dokumen

124

Apa yang salah dengan kode saya untuk mendapatkan nama file di folder dokumen?

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

Saya pikir saya membaca dokumen dengan benar dan saya sangat yakin tentang apa yang ada di folder dokumen, tetapi "fileList" tidak menunjukkan apa-apa? "dir" menunjukkan jalur ke folder.

pawi
sumber
Anda ingin menampilkan nama-nama file yang ada di direktori dokumen atau file yang ada di folder juga?
Adeel Ur Rehman
pertama, hanya file di folder dokumen itu sendiri!
pawi
Saya baru saja menjalankan kode Anda dan berfungsi seperti yang diharapkan. Saya mendapat daftar apa yang ada di direktori dokumen saya. Apakah kami salah memahami pertanyaan Anda?
jwlaughton
Aneh? saya juga menggunakan ".fileExistsAtPath (path)" yang memberitahu saya ada file tertentu. Tapi tidak ada yang muncul di "fileList" !?
pawi
Daftar saya menyertakan direktori dan file.
jwlaughton

Jawaban:

111

Solusi ini berfungsi dengan Swift 4 (Xcode 9.2) dan juga dengan 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)")
}

Berikut adalah ekstensi FileManager yang dapat digunakan kembali yang juga memungkinkan Anda melewati atau menyertakan file tersembunyi dalam hasil:

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
sumber
Bagaimana cara mengecualikan file tersembunyi?
BerbasisMusa
251

Cepat 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
sumber
1
Untuk orang yang ceroboh seperti saya. Perhatikan bahwa panggilan: FileManager.default.contentsOfDirectory (atPath: <# T ## String #>) mungkin tidak berfungsi dengan baik karena alasan yang tidak diketahui di Swift 3.0. Gunakan yang diberikan di atas di sini.
Michael Shang
Jika saya menjalankan ini di direktori iCloud Drive, ini hanya mengembalikan item yang telah diunduh ke perangkat - adakah cara untuk mendapatkan URL dari semua item tanpa mengunduhnya terlebih dahulu?
mralexhay
@mralexhay menunjukkannya untuk saya bahkan item yang tidak diunduh. Ini harus menunjukkan .awalan titik dan .cloudakhiran di nama file. mencobanya let icloudFiles = directoryContents.filter{ $0.pathExtension == "icloud" }harus menunjukkan file yang tidak diunduh
Leo Dabus
1
@LeoDabus terima kasih atas balasannya - Saya tidak menyadarinya menambahkan ".", Saya pikir itu hanya memiliki akhiran "iCloud". Saya menyadari bahwa saya tidak mengembalikan file tersembunyi - tidak heran mereka tidak muncul! Terima kasih lagi.
mralexhay
17

Sintaks yang lebih pendek untuk 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)
}

Contoh penggunaan:

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

Diuji di xCode 8.2.3 untuk iPhone 7 dengan iOS 10.2 & iPad dengan iOS 9.3

Nikita Kurtin
sumber
6

Apple menyatakan tentang NSSearchPathForDirectoriesInDomains(_:_:_:):

Anda harus mempertimbangkan menggunakan FileManagermetode urls(for:in:)dan url(for:in:appropriateFor:create:)yang mengembalikan URL, yang merupakan format yang disukai.


Dengan Swift 5, FileManagermemiliki metode yang disebut contentsOfDirectory(at:includingPropertiesForKeys:options:). contentsOfDirectory(at:includingPropertiesForKeys:options:)memiliki deklarasi berikut:

Melakukan pencarian dangkal dari direktori yang ditentukan dan mengembalikan URL untuk item yang terkandung.

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

Oleh karena itu, untuk mengambil url dari file yang terdapat dalam direktori dokumen, Anda dapat menggunakan potongan kode berikut yang menggunakan FileManager's urls(for:in:)and ' 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)")
}

Sebagai contoh, UIViewControllerimplementasi di bawah ini menunjukkan cara menyimpan file dari app bundle ke direktori dokumen dan cara mendapatkan url dari file yang disimpan di direktori dokumen:

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
sumber
5

Kode ini mencetak semua direktori dan file di direktori dokumen saya:

Beberapa modifikasi fungsi Anda:

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

Yang dipanggil oleh:

    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.dll
sumber
4

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

    }

}

ATAU

 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
sumber
0

Solusi sederhana dan dinamis (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
sumber