【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



【Swift】その URL が ファイル なのか ディレクトリ なのか 存在しないのか

これはディレクトリ。


URL.documentsDirectory

では、これは何を指しているのか。


URL.documentsDirectory.appending(component: "xxx")

ファイルなのか、ディレクトリなのか、存在しないのか。


appendingPathComponent(_:) が Deprecated なので、

👉 appendingPathComponent(_:) | Apple Developer Documentation hatena-bookmark

appending(component:directoryHint:) としています。

👉 appending(component:directoryHint:) | Apple Developer Documentation hatena-bookmark

 

🤔 ディレクトリなのか


print(
  URL.documentsDirectory
    .appending(component: "xxx")
    .hasDirectoryPath
)

// false

👉 hasDirectoryPath | Apple Developer Documentation hatena-bookmark

「ディレクトリではない」のですが、

そのURLにファイルがあるのか、

または、何も存在しないのか、

分かりません。

 

🤔 URL.resourceValues(forKeys:) を使う

👉 resourceValues(forKeys:) | Apple Developer Documentation hatena-bookmark

この形でよく使われています。


extension URL {
  var isDirectory: Bool {
    (try? resourceValues(forKeys: [.isDirectoryKey]))?.isDirectory == true
  }
}


print(
  URL.documentsDirectory
    .isDirectory,
  URL.documentsDirectory
    .appending(component: "xxx")
    .isDirectory
)

// true false

extension 内の条件式の左辺は、


URL先にリソースが存在してディレクトリのとき
→ true

URL先にリソースが存在してディレクトリでないとき
→ false

URL先にリソースが存在しないとき 
→ nil

となります。

URLの指すリソースが、ファイルとディレクトリのみであるとすれば、以下のように書くことができますね!


extension URL {
  private var resourceIsDirectory: Bool? {
    (try? resourceValues(forKeys: [.isDirectoryKey]))?.isDirectory
  }

  var exists: Bool {
    resourceIsDirectory != nil
  }

  var isFile: Bool {
    resourceIsDirectory == false
  }

  var isDirectory: Bool {
    resourceIsDirectory == true
  }
}


let documents = URL.documentsDirectory

print(
  documents.exists,
  documents.isDirectory,
  documents.isFile
)
// true true false

let documentsXXX = URL.documentsDirectory
  .appending(component: "xxx")

print(
  documentsXXX.exists,
  documentsXXX.isDirectory,
  documentsXXX.isFile
)
// false false false

 

🤔 まとめ

URLResourceValues が扱う値はいろいろです。

👉 URLResourceValues | Apple Developer Documentation hatena-bookmark

以下に、まとめておきます。

そもそもは、

「ファイルの存在の確認時に、制限のゆるい String に置き換えてからの FileManager.fileExists(atPath:) を使うのが面倒すぎる。」

ということがきっかけでした。

👉 fileExists(atPath:) | Apple Developer Documentation hatena-bookmark

実体とURLは直感と違います。

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


【macOS】Find and remove all .DS_Store files

🧑🏻‍💻 Terminal から .DS_Store を消す方法

MacのFinderは、各フォルダのメタデータを保存するために .DS_Store ファイルを生成します。しかし、これらのファイルが不要な場合や煩わしい場合もあります。カレントディレクトリ配下のすべての .DS_Store ファイルを確認するには、以下のコマンドを使用します。


find . -type f -name ".DS_Store"

このコマンドは、現在のディレクトリとそのサブディレクトリ内のすべての .DS_Store ファイルをリストアップします。次に、これらのファイルを一括で削除するには、以下のコマンドを実行します。


find . -type f -name ".DS_Store" -delete

これにより、指定されたディレクトリ以下のすべての .DS_Store ファイルが削除され、ディレクトリがクリーンになります。

 

🧑🏻‍💻 .DS_Store ファイルの自動作成を制御する方法

ネットワークドライブや外部ドライブにアクセスする際に .DS_Store ファイルが生成されるのを防ぎたい場合、以下のコマンドを使って自動生成を停止できます。


defaults write com.apple.desktopservices DSDontWriteNetworkStores True
killall Finder

この設定により、これらのドライブに対して .DS_Store ファイルが作成されなくなります。必要に応じて、再度作成を許可する場合は、以下のコマンドを実行します。


defaults write com.apple.desktopservices DSDontWriteNetworkStores False
killall Finder

これにより、元の設定に戻すことができます。

 

🧑🏻‍💻 まとめ

.DS_Store ファイルはFinderのメタデータを保存するために重要な役割を果たしますが、時には不要で煩わしいこともあります。Terminalを使用してこれらのファイルを削除したり、自動生成を制御する方法を知っておくと、作業環境を整えるのに役立ちます。また、macOSのバージョンによっては .DS_Store ファイルの仕様が変わることがあるため、新しいバージョンにアップデートした際には設定を再確認することが重要です。これにより、効率的でスムーズな作業環境を維持できます。

 

🧑🏻‍💻 まとめ

結局、消さないほうがいい。

制御するなら以下のどれかで。


// newtork drive
defaults write com.apple.desktopservices DSDontWriteNetworkStores true
defaults write com.apple.desktopservices DSDontWriteNetworkStores false

// removable drive
defaults write com.apple.desktopservices DSDontWriteUSBStores -bool true
defaults write com.apple.desktopservices DSDontWriteUSBStores -bool false

// finder
defaults write com.apple.finder AppleShowAllFiles -boolean false;killall Finder
defaults write com.apple.finder AppleShowAllFiles FALSE;killall Finder
defaults write com.apple.Finder AppleShowAllFiles TRUE;killall Finder
defaults write com.apple.finder AppleShowAllFiles -boolean true;killall Finder

.gitignore とかリモートクライアントの設定で操作するべし。

Apple の意図は汲んだほうがいいと思える。