【Swift】URL から パス と ファイル名 を区別する方法

ディレクトリを指すURL。


print(URL.documentsDirectory)

ファイルを指すURL。


print(URL.documentsDirectory.appending(component: "new.txt"))

ちょっと分かりづらいので置き換えて。

👉 【Swift】ファイルやディレクトリのパスが長すぎていやだ - URL.shortPath() hatena-bookmark


print(URL.documentsDirectory.shortPath())
// /HOME/Documents/

print(URL.documentsDirectory.appending(component: "new.txt").shortPath())
// /HOME/Documents/new.txt

そもそも、URL.path() は、

URLが


ディレクトリを指す場合は path() の末尾は「/ (スラッシュ)」

というきまりがありますね。

そこで、文字列の分割を2つの関数でやってみます。


let path = URL.documentsDirectory.shortPath()
print(path.split(separator: "/"))
print(path.components(separatedBy: "/"))

// ["HOME", "Documents"]
// ["", "HOME", "Documents", ""]

そんな違いがありますので components(separatedBy:) を使って、


let urlPath = URL.documentsDirectory.shortPath()
let components = urlPath.components(separatedBy: "/")
print("urlPath:", urlPath)
print("path:", components.dropLast().joined(separator: "/") + "/")
print("file:", components.last!)

// urlPath: /HOME/Documents/
// path: /HOME/Documents/
// file:


let urlPath = URL.documentsDirectory.appending(component: "new.txt").shortPath()
let components = urlPath.components(separatedBy: "/")
print("urlPath:", urlPath)
print("path:", components.dropLast().joined(separator: "/") + "/")
print("file:", components.last!)

// urlPath: /HOME/Documents/new.txt
// path: /HOME/Documents/
// file: new.txt

よって、components(separatedBy:) を使った場合、

最終の文字列は、


URLがディレクトリを指してる場合 → 空文字
URLがファイルを指してる場合    → ファイル名

ということになります、

という APIの仕様と既存関数の特性を使った文字列分割でした。

そもそもは、


URL.pathComponents


URL.lastPathComponent

では、ディレクトリかファイルかの区別がない。

ということからこんなことをやってしまいました。

 

🤔 参考


【Swift】ファイルやディレクトリ操作するための extension をまずは作った

ファイルの操作がなんか混乱してストレス。

直感的にまずは作っておく。


FileManager.default.showContents(.temporaryDirectory)

// /HOME/tmp/ 
// /HOME/tmp/.DS_Store [6 kB]
// /HOME/tmp/CFNetworkDownload_1Ji1Ym.tmp [1.8 MB]
// /HOME/tmp/CFNetworkDownload_3ravkG.tmp [1.8 MB]
// /HOME/tmp/CFNetworkDownload_ArezWZ.tmp [1.8 MB]
// /HOME/tmp/CFNetworkDownload_Q2vc3J.tmp [920 kB]
// /HOME/tmp/CFNetworkDownload_WnW3m7.tmp [1.8 MB]
// /HOME/tmp/CFNetworkDownload_s4wpzr.tmp [1.8 MB]

既存の URL、FileManager にぶつからないように作りたい。

あくまで、補助、簡素化。

使い勝手で Gist 更新していきたいです。

いまどきの スマホOS は必要以上の高機能で、

開発者向け SDK や public API までも初心者泣かせの仕様です。


 

🤔 参考

👉 【Swift】FileManager を使いたい hatena-bookmark
👉 【Swift】そのディレクトリ内を再帰的に確認する hatena-bookmark
👉 【Swift】ファイルやディレクトリのパスが長すぎていやだ - URL.shortPath() hatena-bookmark
👉 【Swift】URL で特定のディレクトリやファイルを指す hatena-bookmark
👉 【Swift】その URL が ファイル なのか ディレクトリ なのか 存在しないのか hatena-bookmark


【Swift】ファイルやディレクトリのパスが長すぎていやだ - URL.shortPath()

ファイルやディレクトリを操作していると、

パスの確認をしますよね。

例えば、


let documents = URL.documentsDirectory

としておいて、


print(documents.path)

あれ、Deprecated ですか。


print(documents.path())

として表示すると、


/Users/me/Library/Developer/Xcode/UserData/Previews/Simulator Devices/AA651DE-1A5C-4AA0-80D0-ADC0FF5AA467/data/Containers/Data/Application/35DFAAB4-E576-4318-9F17-DEC9F0DA259A/Documents

長い、長すぎる。

なんせ URL.homeDirectory までが長すぎる。

ファイル操作ごときが、

なぜか辛く感じるのは、

これのせいでしょうか。

短縮形のエクステンソン作ります。

ただの置換です。


extension URL {
  func shortPath(percentEncoded: Bool = true) -> String {
    path(percentEncoded: percentEncoded)
      .replacingOccurrences(
        of: URL.homeDirectory.path(percentEncoded: percentEncoded),
        with: "/HOME/"
      )
  }
}

いくつかの URL で確認。


print(documents.shortPath())
// /HOME/Documents/

print(
  documents
    .appending(component: "Documents and Settings/")
    .shortPath()
)
// /HOME/Documents/Documents%20and%20Settings/

print(
  documents
    .appending(component: "Documents and Settings", directoryHint: .isDirectory)
    .shortPath(percentEncoded: false)
)
// /HOME/Documents/Documents and Settings/

これで、ログウィンドウがスッキリしました!

ごときが !

 

🤔 参考

👉 【Swift】URL で特定のディレクトリやファイルを指す hatena-bookmark