📁
FileManagerでディレクトリの内容を取得する
- iOS/macOSでアプリケーションからファイルシステムにアクセスする
FileManager
- FileManagerでディレクトリの内容を取得(列挙)する方法とできることを紹介
1階層分だけ列挙したい場合
contentsOfDirectory(at:includingPropertiesForKeys:options:)
-
at
で指定したディレクトリのURLに含まれる内容を取得(列挙)する -
includingPropertiesForKeys
で指定したキーに対応したファイルプロパティを事前取得することができる -
options
で列挙する際のオプションを指定できる - 何も指定しないシンプルな例
// for iOS do { let tmpDirectory = FileManager.default.temporaryDirectory let contents = try FileManager.default.contentsOfDirectory( at: tmpDirectory, includingPropertiesForKeys: nil ) print(contents) } catch { print(error) }
サブディレクトリの内容まで列挙したい場合
enumerator(at:includingPropertiesForKeys:options:errorHandler:)
- このメソッド自体は列挙を行う処理ではなく、列挙を行うオブジェクト(
DirectoryEnumerator
)を生成するメソッド - contentsOfDirectoryと同様に、ファイルプロパティの取得と列挙のオプションの指定ができる
-
errorHandler
は列挙の途中でエラーが発生した時に継続するかどうかを決定できるクロージャ - イナムレーターは列挙を行うだけではなく、列挙中にアクセスすることで、現在の階層を取得したりサブディレクトリへの再起を停止させることができる
- 何も指定しないシンプルな例。列挙中に階層を調べて4階層目は列挙しないようにしている
// for macOS do { let homeDirectory = FileManager.default.homeDirectoryForCurrentUser guard let directoryEnumerator = FileManager.default.enumerator( at: templatesDirectory, includingPropertiesForKeys: nil ) else { return } var fileURLs = [URL]() for case let fileURL as URL in directoryEnumerator { // 現在の階層 print(directoryEnumerator.level) fileURLs.append(fileURL) // 4階層(homeDirectoryが0)目以降は列挙しない if directoryEnumerator.level == 3 { directoryEnumerator.skipDescendants() } } print(fileURLs) } catch { print(error) }
ファイルプロパティの取得
- 取得したいプロパティに対応するキー(
URLResourceKey
)を渡すことで、URLオブジェクトに追加の情報を持たせることができる- キーはめっちゃ多いので紹介はしない
- Finderで「情報を見る」で表示する内容とおおよそ同じものを取得できたりする
- 指定したプロパティは
resourceValues(forKeys:)
で取得する - 取得したパスがディレクトリかどうか(
isDirectory
)を一緒に取得しフィルタする例do { let tmpDirectory = FileManager.default.temporaryDirectory // ディレクトリかどうかというプロパティも取得するように指定する let keys: Set<URLResourceKey> = [.isDirectoryKey] let contents = try FileManager.default.contentsOfDirectory( at: tmpDirectory, includingPropertiesForKeys: Array(keys) ) // ディレクトリのものだけにフィルタ let directoryContents = try contents.filter { contentURL in let values = try contentURL.resourceValues(forKeys: keys) // resourceValues(forKeys:)で`.isDirectoryKey`が指定されていない場合はnilとなる return values.isDirectory == true } print(directoryContents) } catch { print(error) }
列挙のオプションを指定する
- オプション(
DirectoryEnumerationOptions
)を指定することで、列挙に条件をつけることができる
skipsSubdirectoryDescendants
- サブディレクトリの内部まで列挙しないようにするオプション
- contentsOfDirectoryでは元々この挙動なので、enumerator専用のオプション
skipsPackageDescendants
- パッケージフォルダ(
.xcodeproj
ファイルなど)をディレクトリではなく、ファイルとみなして子まで列挙しないようにするオプション
skipsHiddenFiles
-
.
で始まる隠しファイル(フォルダ)を列挙しないようにするオプション
includesDirectoriesPostOrder
- 列挙の順序を二分探索における
帰りがけ順(postoder)
で行うようにするオプション- 帰りがけ順の図付きの解説
- 一括削除を行いたい場合に、末端のファイルから安全に削除したい時に有効(らしい)
- 例
// 指定なし file:///Users/me/Downloads/Sample/ file:///Users/me/Downloads/Sample/SampleSub/ file:///Users/me/Downloads/Sample/SampleSub/sample_sub2.txt file:///Users/me/Downloads/Sample/SampleSub/sample_sub1.txt file:///Users/me/Downloads/Sample/sample1.txt file:///Users/me/Downloads/Sample/sample2.txt // 指定あり file:///Users/me/Downloads/Sample/ file:///Users/me/Downloads/Sample/SampleSub/ file:///Users/me/Downloads/Sample/SampleSub/sample_sub2.txt file:///Users/me/Downloads/Sample/SampleSub/sample_sub1.txt file:///Users/me/Downloads/Sample/SampleSub/ file:///Users/me/Downloads/Sample/sample1.txt file:///Users/me/Downloads/Sample/sample2.txt file:///Users/me/Downloads/Sample/
producesRelativePathURLs
- 列挙されるURLオブジェクトを、relativePathを用いたものにするオプション
- 例
// 指定なし file:///Users/me/Downloads/ file:///Users/me/Downloads/Sample/ file:///Users/me/Downloads/Sample/sample.txt // 指定あり Downloads/ -- file:///Users/me/Downloads/ Sample/ -- file:///Users/me/Downloads/ Sample/sample.txt -- file:///Users/me/Downloads/
Discussion