"Bash like" paths to NSURL or Foundation path - swift

In most command line tools, paths to files can be specified using formats like those: ../someFile, ~/anotherFile, /foo/bar. How can I init a valid Swift URL or (Foundation) path from such a path?
EDIT:
Maybe a code example is clearer, say I want to init a String from path and I have a foo file in my user directory, doing this:
try String(contentsOfFile: "~/foo")
Doesn't work (error is file does not exist)

In Swift, you can do :
let str = "~/Documents"
// NSString has a function for decoding this, not available to String:
let str2 = (str as NSString).standardizingPath as String
// Swift deprecated the String path manipulation functions,
// but supplies them as part of NSURL:
let url = URL(fileURLWithPath: str)
let url2 = url.standardizedFileURL // Expands the URL

Related

URL(filePath: strPath) vs URL(fileURLWithPath: strPath)

let url = URL(filePath: pathString!)
let url2 = URL(fileURLWithPath: pathString!)
I tried both and they worked both.
What's the difference between the two ways creating such an URL-object?
String file paths are outmoded. Use file URLs. And not file URLs derived from a string file path; construct or obtain the URL legitimately. So the real answer is: don't use either of those methods.

How to escape a macOS filesystem URL in Swift?

Imagine I want to:
ask the user to enter a file path as a string (which could be something such as 'My' "a/b" folder which in macOS is an entirely acceptable file name.)
create an absolute URL based on the string entered in step 1 eg /Users/john/Desktop/'My' "a/b" folder
do something in a Process with that URL, for example run /bin/mkdir "/Users/john/Desktop/'My' \"a:b\" folder"*
I'm not sure how to achieve this in Swift. I've searched the URL docs and not seen anything to do with macOS's filesystem escaping. I am sure there must be a canonical method to achieve this, and not a series of hopefully-I-covered-the-edge-cases string replacements.
let pathString = """
/Users/john/Desktop/'My' "a/b" folder
"""
let url = URL(fileURLWithPath: pathString)
let urlString = "\"" + url.path + "\""
var process = Process()
process.launchPath = "/bin/mkdir"
process.arguments = [urlString]
I would like urlString to be something like "/Users/john/Desktop/'My' \"a:b\" folder". With that I could create a command such as:
mkdir "/Users/john/Desktop/\'My\'\ \"a\:b\"\ folder"
This is a hypothetical example that illustrates the issue. Of course I'm not actually trying to create a directory using mkdir from within Swift :)
Can you please try this
.addingPercentEncoding(withAllowedCharacters: .urlUserAllowed)

How do I parse out only the files actual name and not the full path?

I have some code that (I thought) could split a filename from its file type. For example, "filename.txt" -> ["filename, "txt"].
However, I didn't realize that when I use a dialog box to open a file name, I get the full path (rookie mistake, I know). For example, this is what my function is returning:
filename_array: ["/home/user/Downloads/filename", "txt"]
How do I remove the path stuff and only return the filename part?
Apple has been trying to get rid of all the "path as string" style and migrate them into URL. The path manipulation API has been removed from String and moved to URL:
let path = "/home/user/Downloads/filename.txt"
let url = URL(fileURLWithPath: path)
let fileNameOnly = url.deletingPathExtension().lastPathComponent // filename
let fileExtention = url.pathExtension // txt
Or you can do it old-school style with NSString:
let path = "/home/user/Downloads/filename.txt"
let fileName = (path as NSString).lastPathComponent as NSString // filename.txt
let fileNameOnly = fileName.deletingPathExtension // filename
let fileExtension = fileName.pathExtension // txt

Where do I get the OSX volume for replacing "/" [duplicate]

When using
let directoryEnumerator = FileManager().enumerator(at: ...
in Swift 3, I get all files from the folder, e.g.
"file:///Volumes/MacOS/fasttemp/Fotos/"
The results are not including the leading path (here "/Volumes/MacOS"). So I get
"file:///fasttemp/Fotos/2005/"
How can I get the fullpath (directly from the enumerator) or convert them. I want to use URL functions, not string function manipulating by assumptions.
If "MacOS" is the name of your current startup disk then "/Volumes/MacOS" is a symbolic link to "/", so both "/fasttemp/Fotos/2005/" and "/Volumes/MacOS/fasttemp/Fotos/" are absolute paths to the same file.
In order to get a unique file name representation you can query
a URL for its canonical path. Example:
let url = URL(fileURLWithPath: "/Volumes/MacOS/Applications/Utilities/")
if let cp = (try? url.resourceValues(forKeys: [.canonicalPathKey]))?.canonicalPath {
print(cp)
}
// Output: "/Applications/Utilities"
This requires macOS 10.12/iOS 10 or later. On older systems you can
use the realpath() system call:
if let rp = url.withUnsafeFileSystemRepresentation ({ realpath($0, nil) }) {
let fullUrl = URL(fileURLWithFileSystemRepresentation: rp, isDirectory: true, relativeTo: nil)
free(rp)
print(fullUrl.path)
}
// Output: "/Applications/Utilities"
Note that you want to use URL wherever possible, from the NSURL documentation:
URL objects are the preferred way to refer to local files. Most
objects that read data from or write data to a file have methods that
accept an NSURL object instead of a pathname as the file reference.
Here’s an example of how to get all the objects from a directory:
import Foundation
let manager = FileManager.default
// Get URL for the current user’s Documents directory
// Use URL instead of path, it’s more flexible and preferred
if let documents = manager.urls(for: .documentDirectory, in: .userDomainMask).first,
// Get an Enumerator for the paths of all the objects in the directory
// but do not descend into directories or packages
let directoryEnumerator = manager.enumerator(at: documents, includingPropertiesForKeys: [URLResourceKey.pathKey], options: [.skipsSubdirectoryDescendants, .skipsPackageDescendants]) {
// iterate through the objects (files, directories, etc.) in the directory
for path in directoryEnumerator {
print(path)
}
}

Cannot delete element in directory in Swift [duplicate]

How is it possible?
let exists = NSFileManager.defaultManager().fileExistsAtPath(path.absoluteString)
print("exists: \(exists)") //false
This is path.absoluteString
//file:///Users/kuna/Library/Developer/CoreSimulator/Devices/92BD140D-5C14-43C4-80D6-904BB9594ED6/data/Containers/Data/Application/5B818832-BB19-4047-A7F8-1487F36868D6/Documents/wishlists/68/147/128/IMG_0006.PNG
And you can see it is there where it should be:
What is going on?
(The code in this answer has been updated for Swift 3 and later.)
Apparently your path variable is a NSURL (describing a file path). To get the path as
a string, use the path property, not absoluteString:
let exists = FileManager.default.fileExists(atPath: path.path)
absoluteString returns the URL in a string format, including
the file: scheme etc.
Example:
let url = URL(fileURLWithPath: "/path/to/foo.txt")
// This is what you did:
print(url.absoluteString)
// Output: file:///path/to/foo.txt
// This is what you want:
print(url.path)
// Output: /path/to/foo.txt
If you want to check if a path exist,you should check path
let url = NSURL(string: "balabala")
let path = url?.path
//Check path