I have a program that accepts a destination folder where files will be created. My program should be able to handle absolute paths as well as relative paths. My problem is that I don't know how to expand ~
to the home directory.
My function to expand the destination looks like this. If the path given is absolute it does nothing otherwise it joins the relative path with the current working directory.
import "path" import "os" // var destination *String is the user input func expandPath() { if path.IsAbs(*destination) { return } cwd, err := os.Getwd() checkError(err) *destination = path.Join(cwd, *destination) }
Since path.Join
doesn't expand ~
it doesn't work if the user passes something like ~/Downloads
as the destination.
How should I solve this in a cross platform way?
~/ (tilde slash) The tilde (~) is a Linux "shortcut" to denote a user's home directory. Thus tilde slash (~/) is the beginning of a path to a file or directory below the user's home directory. For example, for user01, file /home/user01/test. file can also be denoted by ~/test.
Tilde expansion applies to the ' ~ ' plus all following characters up to whitespace or a slash. It takes place only at the beginning of a word, and only if none of the characters to be transformed is quoted in any way. Plain ' ~ ' uses the value of the environment variable HOME as the proper home directory name.
called ~ "). Used in URLs, interpretation of the tilde as a shorthand for a user's home directory (e.g., http://www.foo.org/~bob ) is a convention borrowed from Unix.
Go provides the package os/user, which allows you to get the current user, and for any user, their home directory:
usr, _ := user.Current() dir := usr.HomeDir
Then, use path/filepath to combine both strings to a valid path:
if path == "~" { // In case of "~", which won't be caught by the "else if" path = dir } else if strings.HasPrefix(path, "~/") { // Use strings.HasPrefix so we don't match paths like // "/something/~/something/" path = filepath.Join(dir, path[2:]) }
(Note that user.Current() is not implemented in the go playground (likely for security reasons), so I can't give an easily runnable example).
In general the ~
is expanded by your shell before it gets to your program. But there are some limitations.
In general is ill-advised to do it manually in Go.
I had the same problem in a program of mine and what I have understood is that if I use the flag format as --flag=~/myfile
, it is not expanded. But if you run --flag ~/myfile
it is expanded by the shell (the =
is missing and the filename appears as a separate "word").
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With