Swift: How to expand a tilde in a path String
Tilde expansion
Swift 1
"~/Desktop".stringByExpandingTildeInPath
Swift 2
NSString(string: "~/Desktop").stringByExpandingTildeInPath
Swift 3
NSString(string: "~/Desktop").expandingTildeInPath
Home Directory
Additionally you can get the home directory like this (returns a String
/String?
):
NSHomeDirectory()
NSHomeDirectoryForUser("<User>")
In Swift 3 and OS X 10.12 it's also possible to use this (returns a URL
/URL?
):
FileManager.default().homeDirectoryForCurrentUser
FileManager.default().homeDirectory(forUser: "<User>")
Edit: In Swift 3.1 this got changed to FileManager.default.homeDirectoryForCurrentUser
Tilde-based Paths in Objective-C
Use NSString's stringByExpandingTildeInPath:
method.
There are also several other methods that make it easy to work with paths.
Bash like paths to NSURL or Foundation path
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
Can I use environment variables or tilde in module.modulemap?
No, the modulemap syntax does not expand tildes or environment variables. It ultimately just expects to stat
the path you gave it, and if no file's there, it'll gripe.
- Here's where the header file lookup is kicked off, during lexing of the module map file.
- It ultimately passes the path to the SourceManager's FileManager to produce a
File
object, as here for a header in a framework'sHeaders/
public header folder. getFile
ultimately ends up calling out togetStatValue
, which does a cache lookup.- The
FileSystemStatCache::get
eventually grounds out in LLVM's filesystem abstraction, where it callssys::fs::status
, which is documented to act like POSIXstat
. - POSIX
stat
works with paths as-is, no tilde or environment variable expansion - the common availability of those is due to the shell helping you out, not something that happens automatically most of the time at the system level.
However, it's standard to use relative paths in module maps. The lexer respects this, and all the module map docs demonstrate this. In the common case where your module map file is colocated with your library and installed alongside it, this should suffice to properly resolve the paths.
Expand tilde to home directory
Normally, the ~
is expanded by the shell before your program sees it.
Adjust how your program acquires its arguments from the command line in a way compatible with the shell expansion mechanism.
One of the possible problems is using exec.Command like this:
cmd := exec.Command("some-binary", someArg) // say 'someArg' is "~/foo"
which will not get expanded. You can, for example use instead:
cmd := exec.Command("sh", "-c", fmt.Sprintf("'some-binary %q'", someArg))
which will get the standard ~
expansion from the shell.
EDIT: fixed the 'sh -c' example.
Can not make path to the file in Swift
When using Swift REPL, the NSBundle.mainBundle()
's path actually points to:
/Applications/Xcode6-Beta6.app/Contents/SharedFrameworks/LLDB.framework/Versions/A/Resources
You may have to use NSFileManager instead:
let manager = NSFileManager.defaultManager()
if manager.fileExistsAtPath("/Users/tsypa/a.txt") {
// file exists, read
} else {
// file doesn't exist
}
Note: You can actually automatically expand tilde in the path to avoid hardcoding the full user's home path:
"~/a.txt".stringByExpandingTildeInPath // prints /Users/<your user>/a.txt
Why is zsh not able to read ~ (tilde) from a path in a script?
Use the following code to get what you want:
export PATH=~/Desktop/Capture/
echo $PATH
# Result: /Users/swift/Desktop/Capture/
Although, when you're using a string, you'll get this:
export PATH="~/Desktop/Capture/"
echo $PATH
# Result: ~/Desktop/Capture/
So to get it right, you'll have to try this approach:
tilde=~
export PATH="${tilde}/Desktop/Capture/"
echo $PATH
# Result: /Users/swift/Desktop/Capture/
P.S. Also, there's one useful command for tilde to be expanded.
Here's an example:
echo tilda=~
# Result: tilda=~
Use magicequalsubst
command in zsh
:
set -o magicequalsubst
echo tilda=~
# Result: tilda=/Users/swift
How would I resolve a relative path in Objective-C?
Below is my solution which is working well which uses a lower level C function which I was trying to avoid. It is working for my purposes. The full project which uses is available on GitHub with the method I created for Objective-C below.
https://github.com/brennanMKE/Xcode4CodeSnippets/tree/master/SnippetImporter
- (NSString *)resolvePath:(NSString *)path {
NSString *expandedPath = [[path stringByExpandingTildeInPath] stringByStandardizingPath];
const char *cpath = [expandedPath cStringUsingEncoding:NSUTF8StringEncoding];
char *resolved = NULL;
char *returnValue = realpath(cpath, resolved);
if (returnValue == NULL && resolved != NULL) {
printf("Error with path: %s\n", resolved);
// if there is an error then resolved is set with the path which caused the issue
// returning nil will prevent further action on this path
return nil;
}
return [NSString stringWithCString:returnValue encoding:NSUTF8StringEncoding];
}
Related Topics
Unsafemutablepointer<Uint8> to [Uint8] Without Memory Copy
What Is Import Func, Struct, Class, and @_Exported in Swift
How to Initialise Cvpixelbufferref in Swift
How to Create a Hud on Top of My Scenekit.Scene
How to Retrieve the Type of an Object in Swift
Sprite-Kit: Moving an Element in Circular Path
Resetting Zone Allocator with Allocations Still Alive
Swift, Avaudiorecorder: Error 317: Ca_Debug_String: Inpropertydata == Null
A Different Bridging Between Array and Dictionary
How to Save Cgimage to Data in Swift
Uiimage Created from Mtkview Results in Color/Opacity Differences
How to Subclass Custom Uiviewcontroller in Swift
Using Apple's New Audioengine to Change Pitch of Audioplayer Sound
How to Make a Local Module with the Swift Package Manager
Swift: How to Disable User Interaction While Touch Action Is Being Carried Out
Why Does Filters in Swift Iterate the Collection Twice
How to Extract Image from Lplinkview in Linkpresentation Framework