web-dev-qa-db-ja.com

SwiftのFileManagerを使用して、フォルダーおよびそのサブフォルダー内のファイルを反復処理します

Swiftをプログラミングするのは初めてで、フォルダー内のファイルを繰り返し処理しようとしています。答え here を見て、Swift構文に変換しようとしましたが、成功しませんでした。

let fileManager = NSFileManager.defaultManager()
let enumerator:NSDirectoryEnumerator = fileManager.enumeratorAtPath(folderPath)

for element in enumerator {
    //do something
}

私が得るエラーは:

Type 'NSDirectoryEnumerator' does not conform to protocol 'SequenceType'

私の目的は、メインフォルダーに含まれるすべてのサブフォルダーとファイルを調べて、特定の拡張子を持つすべてのファイルを見つけて、それらで何かをすることです。

65

enumeratorの-​​ nextObject() メソッドを使用します。

while let element = enumerator?.nextObject() as? String {
    if element.hasSuffix("ext") { // checks the extension
    }
}
73
pNre

最近(2017年初頭)、より汎用性の高いURL関連のAPIを使用することを強くお勧めします

let fileManager = FileManager.default

do {
    let resourceKeys : [URLResourceKey] = [.creationDateKey, .isDirectoryKey]
    let documentsURL = try fileManager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
    let enumerator = FileManager.default.enumerator(at: documentsURL,
                            includingPropertiesForKeys: resourceKeys,
                                               options: [.skipsHiddenFiles], errorHandler: { (url, error) -> Bool in
                                                        print("directoryEnumerator error at \(url): ", error)
                                                        return true
    })!

    for case let fileURL as URL in enumerator {
        let resourceValues = try fileURL.resourceValues(forKeys: Set(resourceKeys))
        print(fileURL.path, resourceValues.creationDate!, resourceValues.isDirectory!)
    }
} catch {
    print(error)
}
52
vadian

私はpNreのソリューションをまったく動作させることができませんでした。 whileループは何も受信しませんでした。しかし、私はこの解決策に出くわしました(Xcode 6ベータ6では、pNreが上記の回答を投稿してから状況が変わったのでしょうか?):

for url in enumerator!.allObjects {
    print("\((url as! NSURL).path!)")
}
18

ディレクトリ内のすべてのファイル+サブディレクトリを返します

import Foundation

let path = "<some path>"

let enumerator = FileManager.default.enumerator(atPath: path)

while let filename = enumerator?.nextObject() as? String {
        print(filename)
}
7
Alex Shubin

あなたが得ている場合

'NSDirectoryEnumerator?'には'nextObject'という名前のメンバーがありません

whileループは次のようになります。

while let element = enumerator?.nextObject() as? String {
  // do things with element
}

オプションの連鎖 と関係があります

5
user1398498

スイフト3

let fd = FileManager.default
fd.enumerator(atPath: "/Library/FileSystems")?.forEach({ (e) in
    if let e = e as? String, let url = URL(string: e) {
        print(url.pathExtension)
    }
})
5
user3441734

Swift3 +絶対URL

extension FileManager {
    func listFiles(path: String) -> [URL] {
        let baseurl: URL = URL(fileURLWithPath: path)
        var urls = [URL]()
        enumerator(atPath: path)?.forEach({ (e) in
            guard let s = e as? String else { return }
            let relativeURL = URL(fileURLWithPath: s, relativeTo: baseurl)
            let url = relativeURL.absoluteURL
            urls.append(url)
        })
        return urls
    }
}

@ user3441734 のコードに基づく

4
neoneye

Swift 3.

渡されたディレクトリとそのサブディレクトリ内の拡張子を持つすべてのファイルを返します

func extractAllFile(atPath path: String, withExtension fileExtension:String) -> [String] {
    let pathURL = NSURL(fileURLWithPath: path, isDirectory: true)
    var allFiles: [String] = []
    let fileManager = FileManager.default
    let pathString = path.replacingOccurrences(of: "file:", with: "")
    if let enumerator = fileManager.enumerator(atPath: pathString) {
        for file in enumerator {
            if #available(iOS 9.0, *) {
                if let path = NSURL(fileURLWithPath: file as! String, relativeTo: pathURL as URL).path, path.hasSuffix(".\(fileExtension)"){
                    let fileNameArray = (path as NSString).lastPathComponent.components(separatedBy: ".")
                    allFiles.append(fileNameArray.first!)
                }
            } else {
                // Fallback on earlier versions
                print("Not available, #available iOS 9.0 & above")
            }
        }
    }
    return allFiles
}
4
Ranjith

以前のanwersから私の2セント..より迅速かつオプションで:

 let enumerator = FileManager.default.enumerator(atPath: folderPath)
    while let element = enumerator?.nextObject() as? String {
        print(element)

        if let fType = enumerator?.fileAttributes?[FileAttributeKey.type] as? FileAttributeType{

            switch fType{
            case .typeRegular:
                print("a file")
            case .typeDirectory:
                print("a dir")
            }
        }

    }
2
ingconti

Swift 3の更新:

let fileManager = FileManager()     // let fileManager = NSFileManager.defaultManager()
let en=fileManager.enumerator(atPath: the_path)   // let enumerator:NSDirectoryEnumerator = fileManager.enumeratorAtPath(folderPath)

while let element = en?.nextObject() as? String {
    if element.hasSuffix("ext") {
        // do something with the_path/*.ext ....
    }
}
2
dawg

Vadianの応答に追加-Appleのドキュメントには、パスベースのURLがいくつかの点でより簡単であると記載されていますが、ファイル参照URLには、アプリの移動中にファイルを移動または名前変更しても参照が有効であるという利点がありますランニング。

「ファイルとディレクトリへのアクセス」のドキュメントから:

「パスベースのURLは操作が簡単で、デバッグが簡単で、NSFileManagerなどのクラスで一般的に好まれます。ファイル参照URLの利点は、アプリの実行中にパスベースのURLよりも壊れにくいことです。 Finderでファイルを移動すると、そのファイルを参照するパスベースのURLはすぐに無効になり、新しいパスに更新する必要がありますが、ファイルが同じディスク上の別の場所に移動する限り、その一意のIDは変更してもファイル参照URLはすべて有効です。」

https://developer.Apple.com/library/content/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/AccessingFilesandDirectories/AccessingFilesandDirectories.html

1
dougzilla

参照URLは避けてください。上記のようにいくつかの利点がありますが、システムリソースを消費します。また、大きなファイルシステム(実際にはそれほど大きくない)を列挙している場合、アプリはシステムの壁にすばやくぶつかり、macOSによってシャットダウンされます。

0
David Hitchen

最近、ディレクトリであるかどうかにかかわらず、URLの配列を処理する際にこれに苦労しました(ドラッグアンドドロップなど)。 Swift 4にこの拡張機能が追加されたため、役に立つかもしれません

extension Sequence where Iterator.Element == URL {

    var handleDir: [URL] {
        var files: [URL] = []
        self.forEach { u in
            guard u.hasDirectoryPath else { return files.append(u.resolvingSymlinksInPath()) }
            guard let dir = FileManager.default.enumerator(at: u.resolvingSymlinksInPath(), includingPropertiesForKeys: nil) else { return }
            for case let url as URL in dir {
                files.append(url.resolvingSymlinksInPath())
            }
        }
        return files
    }
}
0
Joe Maher

要素がファイルかサブディレクトリかをカテゴリ別に確認する場合:

let enumerator = FileManager.default.enumerator(atPath: contentsPath);
while let element = enumerator?.nextObject() as? String {             
   if(enumerator?.fileAttributes?[FileAttributeKey.type] as! FileAttributeType == FileAttributeType.typeRegular){
                //this is a file
   }
   else if(enumerator?.fileAttributes?[FileAttributeKey.type] as! FileAttributeType == FileAttributeType.typeDirectory){ 
                //this is a sub-directory
    }
}
0
Chris Amelinckx