Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Expand tilde to home directory

Tags:

path

go

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?

like image 526
lukad Avatar asked Jul 12 '13 07:07

lukad


People also ask

How do you put a tilde in a path?

~/ (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.

What is tilde expansion?

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.

What does tilde mean in Windows path?

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.


2 Answers

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).

like image 56
joshlf Avatar answered Oct 08 '22 15:10

joshlf


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").

like image 39
Anastasios Andronidis Avatar answered Oct 08 '22 14:10

Anastasios Andronidis