Belgeler klasöründeki dosyaların listesini alma


124

Belge klasöründeki dosya adlarını almak için kodumda sorun nedir?

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

Belgeleri doğru okuduğumu düşündüm ve belgeler klasöründe ne olduğundan çok eminim, ancak "dosyaListesi" hiçbir şey göstermiyor mu? "dir" klasörün yolunu gösterir.


belge dizininde bulunan dosyaların adlarını mı yoksa klasörlerdeki dosyaların adlarını da göstermek ister misiniz?
Adeel Ur Rehman

önce, yalnızca belge klasöründeki dosyalar!
pawi

Kodunuzu çalıştırdım ve beklendiği gibi çalıştı. Belgeler dizinimde olanların bir listesi var. Sorunuzu yanlış mı anlıyoruz?
jwlaughton

Garip? Ayrıca bana belirli bir dosyanın mevcut olduğunu söyleyen ".fileExistsAtPath (yol)" kullandım. Ama "fileList" de hiçbir şey görünmüyor !?
pawi

Listem hem dizinleri hem de dosyaları içeriyordu.
jwlaughton

Yanıtlar:


112

Bu çözüm Swift 4 (Xcode 9.2) ve ayrıca Swift 5 (Xcode 10.2.1+) ile çalışır:

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

İşte sonuçlara gizli dosyaları atlamanıza veya eklemenize olanak tanıyan yeniden kullanılabilir bir FileManager uzantısı:

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

Gizli dosyaları nasıl dışlayabilirim?
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)
}

1
Benim kadar dikkatsiz insanlar için. Not: FileManager.default.contentsOfDirectory (atPath: <# T ## String #>), Swift 3.0'da bilinmeyen nedenlerle düzgün çalışmayabilir. Burada yukarıda verileni kullanın.
Michael Shang

Bunu bir iCloud Drive dizininde çalıştırırsam, yalnızca aygıta indirilen öğeleri döndürür - tüm öğelerin URL'lerini önce indirmeden almanın bir yolu var mı?
mralexhay

@mralexhay indirilmemiş öğeleri bile benim için gösteriyor. Dosya adında bir nokta .öneki ve bir .cloudson ek göstermelidir . deneyin let icloudFiles = directoryContents.filter{ $0.pathExtension == "icloud" }indirilmemiş dosyaları göstermeli
Leo Dabus

1
@LeoDabus cevap için teşekkürler - "." Nin başına eklendiğini fark etmemiştim, sadece "iCloud" son eki olduğunu düşünmüştüm. Gizli dosyaları iade etmediğimi fark ettim - gösterilmemelerine şaşmamalı! Tekrar teşekkürler.
mralexhay

17

SWIFT 3 için daha kısa bir sözdizimi

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

Kullanım örneği:

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

İOS 10.2 yüklü iPhone 7 ve iOS 9.3 yüklü iPad için xCode 8.2.3'te test edilmiştir


6

Apple şu konularda belirtiyor NSSearchPathForDirectoriesInDomains(_:_:_:):

FileManagerYöntemleri urls(for:in:)ve url(for:in:appropriateFor:create:)tercih edilen biçim olan hangi URL'leri döndürmeyi düşünmelisiniz .


Swift 5 ile. Adında FileManagerbir yöntemi var contentsOfDirectory(at:includingPropertiesForKeys:options:). contentsOfDirectory(at:includingPropertiesForKeys:options:)aşağıdaki beyana sahiptir:

Belirtilen dizinde yüzeysel bir arama gerçekleştirir ve içerilen öğeler için URL'leri döndürür.

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

Bu nedenle, belgeler dizininde bulunan dosyaların url'lerini almak için FileManager's urls(for:in:)ve contentsOfDirectory(at:includingPropertiesForKeys:options:)yöntemlerini kullanan aşağıdaki kod parçacığını kullanabilirsiniz :

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

Örnek olarak, aşağıdaki UIViewControlleruygulama, bir dosyanın uygulama paketinden belgeler dizinine nasıl kaydedileceğini ve belgeler dizinine kaydedilen dosyaların url'lerinin nasıl alınacağını gösterir:

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

Bu kod, belgeler dizinimdeki tüm dizinleri ve dosyaları yazdırır:

İşlevinizde bazı değişiklikler:

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

Hangi tarafından çağrılır:

    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

Swift 2.0 Uyumluluğu

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

    }

}

VEYA

 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

Basit ve dinamik çözüm (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
  }}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.