Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Listing (only) the subfolders within a folder -- Swift 3.0 / iOS 10 [duplicate]

I'm attempting to get a list of all subfolders within a folder (the app's Documents directory, in the example below). The code below successfully finds everything in the folder (files + folders both), and also finds the files with the specified .text extension, but I'm failing to narrow the results to just a list of the subdirectories.

let filemgr = FileManager.default
var dirPaths = filemgr.urls(for: .documentDirectory, in: .userDomainMask)
myDocumentsDirectory = dirPaths[0]

var r = "Directory Listing:\n------------------\n" // r = will be returned (or displayed in this case)

do {
    let directoryContents = try FileManager.default.contentsOfDirectory(at: myDocumentsDirectory, includingPropertiesForKeys: nil, options: [])

    // all files -- works fine
    let allFileNames = directoryContents.map{ $0.deletingPathExtension().lastPathComponent }
    r += "All file names:\n\(allFileNames)\n\n"

    // filtering for text files -- also works fine
    let textFiles = directoryContents.filter{ $0.pathExtension == "text" }
    let textFileNames = textFiles.map{ $0.deletingPathExtension().lastPathComponent }
    r += "text file list:\n\(textFileNames)\n\n"

    // Look for folders within the folder -- fails, nothing returned            
    let subdirs = directoryContents.filter{ !$0.isFileURL }
    let subdirNames = subdirs.map{ $0.deletingPathExtension().lastPathComponent }

    r += "Subdirectories:\n\(subdirNames)\n\n"
    textView.text = r

} catch let error as NSError {
    print(error.localizedDescription)

I can pick up all the directories by setting the filter to

$0.pathExtension == ""

but that also picks up any files in the directory with no extension -- i.e. it correctly excludes foo.bar but incorrectly includes the file foo along with the folders, and that isn't what I need -- has to be only the directories & nothing more.

Also, I'm not trying to look deeper into sub-folders within sub-folders -- just the ones "here" is all I'm looking for.

Any suggestions will be much appreciated!

like image 252
ConfusionTowers Avatar asked Mar 20 '17 01:03

ConfusionTowers


People also ask

How can I get a list of all the subfolders and files present in a directory using PHP?

PHP using scandir() to find folders in a directory The scandir function is an inbuilt function that returns an array of files and directories of a specific directory. It lists the files and directories present inside the path specified by the user.

How do I list files in a subfolder?

The dir command displays a list of files and subdirectories in a directory. With the /S option, it recurses subdirectories and lists their contents as well. Options listed below may be preset in the DIRCMD environment variable.


2 Answers

You can pass URLResourceKey.isDirectoryKey to the includingPropertiesForKeys parameter in your contentsOfDirectory method call on line 6. This should return that particular attribute for all your returned URLs. Then, you can check the attribute to see if each URL is for a directory or a file ...

If you are wondering how to get at the attributes for the fetched URLs, then take a look at the resourceValues method for the URL class :)

like image 100
Fahim Avatar answered Oct 07 '22 02:10

Fahim


Fahim's answer, specifically the resourceValues method for the URL class, is what I needed; for completeness & to help out anybody who finds this question later, here is the final code that gets exactly what I wanted, while keeping the same basic structure:

let filemgr = FileManager.default
var dirPaths = filemgr.urls(for: .documentDirectory, in: .userDomainMask)
myDocumentsDirectory = dirPaths[0]

do {
    let directoryContents = try FileManager.default.contentsOfDirectory(at: myDocumentsDirectory, includingPropertiesForKeys: nil, options: [])

    let onlyFileNames = directoryContents.filter{ !$0.hasDirectoryPath }
    let onlyFileNamesStr = onlyFileNames.map { $0.lastPathComponent }

    let subdirs = directoryContents.filter{ $0.hasDirectoryPath }
    let subdirNamesStr = subdirs.map{ $0.lastPathComponent }

    // now do whatever with the onlyFileNamesStr & subdirNamesStr
} catch let error as NSError {
    print(error.localizedDescription) 
}
like image 27
ConfusionTowers Avatar answered Oct 07 '22 02:10

ConfusionTowers