Как использовать NSURL с относительным путем?

#swift #macos #command-line

#swift #macos #командная строка

Вопрос:

Итак, я создаю инструмент командной строки в Swift, который принимает путь к файлу в качестве аргумента. Я проверяю, существует ли путь к файлу, иначе я выдаю ошибку. Когда я использую абсолютный путь, все работает так, как должно. Когда я использую относительный путь, это не так.

код:

   let pwdURL = URL(string: "file://"   FileManager.default.currentDirectoryPath)
  print("pwdURL: ", pwdURL ?? "no pwdURL")
  let pathURL = URL(string: path, relativeTo: pwdURL)
  print("pathURL: ", pathURL ?? "no pathURL")

  do {
    let _ = try pathURL?.checkResourceIsReachable()
  }
    catch {
    print(error)
    throw ValidationError("(path) Is not a valid path.")
  }
 

команда:

Из /Users/myUser/Projects/myProject папки, в терминале.

   swift run myProject ../../Downloads/myFile.pdf
 

вывод:

   pwdURL:  file:///Users/myUser/Projects/myProject
  pathURL:  ../../Downloads/myFile.pdf -- file:///Users/myUser/Projects/myProject
  
  Error Domain=NSCocoaErrorDomain Code=260 "The file “myFile.pdf” couldn’t be opened because there is no such file." UserInfo={NSURL=../../Downloads/myFile.pdf -- file:///Users/myUser/Projects/myProject, NSFilePath=/Users/Downloads/myFile.pdf, NSUnderlyingError=0x7fad39d0c280 {Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory"}}
  Error: ../../Downloads/myFile.pdf Is not a valid path.
 

Я ожидал, что он будет искать /Users/myUser/Downloads/myFile.pdf , потому что это допустимый путь, с которого я ввожу команду в терминале. Кроме того, когда я смотрю на вывод из pathURL ( ../../Downloads/myFile.pdf -- file:///Users/myUser/Projects/myProject ), похоже, что это приведет к правильному пути?
Но, как вы можете видеть, возникает ошибка, потому что он ищет /Users/Downloads/myFile.pdf , которого не существует.

Ответ №1:

Требуется, чтобы relativeTo параметр заканчивался на a / , чтобы это работало так, как вы ожидаете. Из документов NSURL (курсив добавлен):

Этот метод позволяет создать URL-адрес относительно базового пути или URL-адреса. Например, если у вас есть URL-адрес папки на диске и имя файла в этой папке, вы можете создать URL-адрес для файла, указав URL-адрес папки в качестве базового пути (с завершающей косой чертой) и имя файла в качестве строковой части.

Итак, что вам нужно здесь:

 let pwdURL = URL(string: "file://"   FileManager.default.currentDirectoryPath   "/")
 

Но я бы на самом деле сделал это так:

 let pwdURL = URL(fileURLWithPath: FileManager.default.currentDirectoryPath)
 

или:

 let pwdURL = Process().currentDirectoryURL
 

Обычно мне проще это сделать, используя appendingPathComponent , что немного проще в правильном использовании:

 let pathURL = pwdURL.appendingPathComponenent(path)
 

Разница в том, что это оставит ../.. путь, а не разрешит их, так что это зависит от того, что вы хотите.

Комментарии:

1. Другой вариант — создать базовый URL с URL(fileURLWithPath: ..., isDirectory: true)

2. хех; Я просто дважды проверял, как это сделать правильно.