Перебирать файлы в папке и ее вложенных папок с помощью файлового менеджера Свифт
Я довольно новыми для программирования Swift и я пытаюсь перебирать файлы в папке.
Я взглянул на ответ здесь и попытался перевести его на синтаксис 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'
моя цель-посмотреть на все подпапки и файлы, содержащиеся в главной папке, и найти все файлы с определенным расширением, чтобы затем что-то с ними сделать.
13 ответов:
использовать
nextObject()методenumerator:while let element = enumerator?.nextObject() as? String { if element.hasSuffix("ext") { // checks the extension } }
В настоящее время (в начале 2017 года) настоятельно рекомендуется использовать API, связанный с более универсальным URL – адресом
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) }
Я не мог заставить решение pNre работать вообще; цикл while просто никогда ничего не получал. Тем не менее, я столкнулся с этим решением, которое работает для меня (в Xcode 6 beta 6, так что, возможно, все изменилось с тех пор, как pNre опубликовал вышеуказанный ответ?):
for url in enumerator!.allObjects { print("\((url as! NSURL).path!)") }
в случае, если вы получаете
' NSDirectoryEnumerator?- не имеет элемент с именем 'nextObject'
цикл while должен быть:
while let element = enumerator?.nextObject() as? String { // do things with element }Это как-то связано с дополнительные цепочки
Swift 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) } })
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
SWIFT 3.0
возвращает все файлы с расширением в переданном каталоге и его подкаталогах
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 }
возвращает все файлы в директории
Swift 3
let fileNames = try! FileManager.default.contentsOfDirectory(atPath: "/Volumes/Seagate/Path/") for fileName in fileNames { print(fileName) }
обновление для 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 .... } }
добавление к ответу vadian -- в документах Apple упоминается, что URL-адреса на основе пути в некоторых отношениях проще, однако URL-адреса ссылок на файлы имеют то преимущество, что ссылка остается действительной, если файл перемещается или переименовывается во время работы вашего приложения.
из документации для "доступа к файлам и каталогам":
"URL-адреса на основе пути легче манипулировать, легче отлаживать и, как правило, предпочитают такие классы, как NSFileManager. Преимущество ссылки на файл URL-адреса - это то, что они менее уязвимы, чем URL-адреса на основе пути во время работы вашего приложения. Если пользователь перемещает файл в Finder, все URL-адреса на основе пути, которые ссылаются на файл, немедленно становятся недействительными и должны быть обновлены до нового пути. Однако до тех пор, пока файл перемещается в другое место на том же диске, его уникальный идентификатор не изменяется, и все URL-адреса ссылок на файлы остаются действительный."
Если вы хотите категорически проверить, является ли элемент файлом или подкаталогом:
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 } }
недавно боролся с этим при обращении массив 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 } }
избегайте ссылочных URL-адресов, хотя у них есть некоторые преимущества, как указано выше, они едят системные ресурсы, и если вы перечисляете большую файловую систему (не такую большую на самом деле), ваше приложение быстро ударит по системной стене и отключится от macOS.
Comments