Lấy danh sách các tập tin trong thư mục tài liệu


124

Có gì sai với mã của tôi để lấy tên tệp trong thư mục tài liệu?

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

Tôi nghĩ rằng tôi đã đọc các tài liệu một cách chính xác và tôi rất chắc chắn về những gì trong thư mục tài liệu, nhưng "fileList" không hiển thị gì? "dir" hiển thị đường dẫn đến thư mục.


Bạn muốn hiển thị tên của các tệp trong thư mục tài liệu hoặc các tệp trong thư mục?
Adeel Ur Rehman

đầu tiên, chỉ các tập tin trong thư mục tài liệu chính nó!
pawi

Tôi chỉ chạy mã của bạn và nó hoạt động như mong đợi. Tôi có một danh sách những gì trong thư mục tài liệu của tôi. Chúng tôi có hiểu nhầm câu hỏi của bạn không?
jwlaughton

Lạ nhỉ? tôi cũng đã sử dụng ".fileExistsAtPath (path)" để cho tôi biết một tệp cụ thể có mặt. Nhưng không có gì xuất hiện trong "fileList"!?
pawi

Danh sách của tôi bao gồm cả thư mục và tập tin.
jwlaughton

Câu trả lời:


111

Giải pháp này hoạt động với Swift 4 (Xcode 9.2) và cả với 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)")
}

Đây là một tiện ích mở rộng Trình quản lý tệp có thể sử dụng lại cũng cho phép bạn bỏ qua hoặc bao gồm các tệp ẩn trong kết quả:

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

Làm thế nào tôi có thể loại trừ các tập tin ẩn?
DựaMusa

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
Đối với những người bất cẩn như tôi. Lưu ý rằng lệnh gọi: FileManager.default.contentsOfDirectory (atPath: <# T ## String #>) có thể không hoạt động chính xác vì những lý do không xác định trong Swift 3.0. Sử dụng một trong những ở trên ở đây.
Michael Shang

Nếu tôi chạy cái này trên thư mục iCloud Drive, nó chỉ trả về các mục đã được tải xuống thiết bị - có cách nào để lấy URL của tất cả các mục mà không tải xuống trước không?
mralexhay

@mralexhay nó hiển thị cho tôi ngay cả những mục không được tải xuống. Nó sẽ hiển thị một .tiền tố dấu chấm và một .cloudhậu tố trong tên tệp. Hãy thử let icloudFiles = directoryContents.filter{ $0.pathExtension == "icloud" }nó sẽ hiển thị các tệp không được tải xuống
Leo Dabus

1
@LeoDabus cảm ơn vì đã trả lời - Tôi đã không nhận ra nó trả trước ".", Tôi nghĩ rằng nó chỉ có hậu tố "iCloud". Tôi nhận ra rằng tôi đã không trả lại các tập tin ẩn - không có gì ngạc nhiên khi chúng không hiển thị! Cảm ơn một lần nữa.
mralexhay

17

Cú pháp ngắn hơn cho 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)
}

Ví dụ sử dụng:

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

Đã thử nghiệm trên xCode 8.2.3 cho iPhone 7 với iOS 10.2 & iPad với iOS 9.3


6

Apple tuyên bố về NSSearchPathForDirectoriesInDomains(_:_:_:):

Bạn nên cân nhắc sử dụng các FileManagerphương thức urls(for:in:)url(for:in:appropriateFor:create:)trả về URL nào là định dạng ưa thích.


Với Swift 5, FileManagercó một phương thức gọi là contentsOfDirectory(at:includingPropertiesForKeys:options:). contentsOfDirectory(at:includingPropertiesForKeys:options:)có tuyên bố sau:

Thực hiện tìm kiếm nông của thư mục được chỉ định và trả về URL cho các mục được chứa.

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

Do đó, để truy xuất các url của các tệp có trong thư mục tài liệu, bạn có thể sử dụng đoạn mã sau sử dụng FileManagercác phương thức urls(for:in:)contentsOfDirectory(at:includingPropertiesForKeys:options:)phương thức:

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

Ví dụ, cách UIViewControllertriển khai bên dưới cho thấy cách lưu tệp từ gói ứng dụng vào thư mục tài liệu và cách lấy url của các tệp được lưu trong thư mục tài liệu:

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

Mã này in ra tất cả các thư mục và tệp trong thư mục tài liệu của tôi:

Một số sửa đổi chức năng của bạn:

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

Mà được gọi bởi:

    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

Khả năng tương thích 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)
       ........
        }

    }

}

HOẶC LÀ

 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

Giải pháp đơn giản và năng động (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
  }}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.