24

Can we use $HOME or other environment variable in symbolic links?

I know about using relative paths ../../.config but sometimes are to many ../ :) something like ~/.config would be more comfortable, or use of $HOME.

Edit:

habbie's answer with psmears's comment is the answer, sorry my question was incomplete.

While (as other answers show) you can use environment variables when creating symbolic links (as with any shell command!), you can't actually have environment variable (or '~') references in the symlink itself

Community
  • 1
  • 1
kfl62
  • 2,434
  • 4
  • 29
  • 40
  • 2
    I wish this was possible. One use case: you have a bunch of symlinks in a ~/bin directory that points to, say, scripts in a personal git repository cloned to `$HOME/my_github_scripts`. You want to link to these scripts from the `~/bin` directory on several machines, but your username is different. So you don't want to hardcode the username (it might be `/home/joebloggs` on my home computer but `/home/jbloggs` at work, or even `/Users/joebloggs` on a Mac). – Sridhar Sarnobat Sep 12 '14 at 22:31
  • If want to try something exotic you can look into ROFS Filtered. –  Jan 17 '16 at 14:08

7 Answers7

49

Symbolic links are handled by the kernel, and the kernel does not care about environment variables. So, no.

Habbie
  • 2,150
  • 15
  • 17
  • 16
    Not sure who modded this down without leaving a comment - the answer is correct. While (as other answers show) you can use environment variables when *creating* symbolic links (as with any shell command!), you can't actually have environment variable (or '~') references in the symlink itself. – psmears Oct 08 '10 at 08:30
  • 1
    could you by any chance link the relevant source file in the kernel? – n611x007 Nov 06 '14 at 13:48
  • 2
    Sadly, it's not correct for all Unixen, since there is a least one version of Unix around 1990 or so that would interpret variables in symlinks exactly as described on the fly every time the link was used. One common use was to get $ARCH into symlinks out to bin directories in heterogeneous clusters using NFS filesystems across everything. – Alex North-Keys Jan 22 '16 at 01:15
3

Even though the symbolic links are resolved by the kernel, you could still do a LD_PRELOAD trick, wrapping all libc functions that take pathnames and expand any $XYZ components in the string returned by 'readlink' (parameter expansion). Then feed the expanded path to the wrapped function. You have to escape the target path from shell expansion when creating the link, as jaztik suggests.

As the injected library has full access to the users' environment, this will fulfill all expectations of the OP.

2

If you don't want to expand the variable in the link you can put single quotes around it,

ln -s '$HOME/file/or/folder' newname

This would give,

newname -> $HOME/file/or/folder

rather than have it expand to your locally set $HOME. As described in other answers it will not expand it at all. So you can e.g. use it to symlink to a file inside the literal $HOME folder.

[Note this is system dependent - not all systems support variant symlinks]

Jonathan
  • 752
  • 8
  • 18
jazstik
  • 29
  • 2
  • I'm curious if you can name one system that *does*? :) – conny Sep 25 '11 at 15:37
  • I seem to be able to do this on OS X 10.9. – JacobEvelyn Jun 11 '14 at 20:31
  • 2
    @JacobEvelyn Just tried on OS X 10.9. It correctly stored the environment variable name in the link (`/tmp/currenthome -> $HOME`) - but the link target could not be successfully resolved. (`-bash: cd: /tmp/currenthome: No such file or directory`) – Jason Musgrove Jun 24 '14 at 12:58
  • 2
    Domain/OS on Apollo (and I think DEC/Ultrix on Alpha) had variant symlinks. They where nice and a little nightmare at the same time :-) – Rmano Jan 29 '15 at 08:38
1

yes. no problem. actually you won't actually be using the $HOME variable in your link, so it won't work with smart solutions for groups of users for example. The variable is translated by the shell when executing the command, and the content of the variable is used in the link.

ln -s ~/test /tmp/test 

is expaned to

/<path>/<to>/home/test -> /tmp/test

Ah. and only the environment variables of the person calling ln will work. You can't store other peoples environment variables in the link. The variables are expanded before calling the command.

thomasmalt
  • 1,718
  • 11
  • 15
  • I just tried this on a Centos box and what thomasmalt writes is correct. The variable will be translated at the point of creating the symbolic link, and will not be dynamically updated if you change the environment variable. –  Oct 08 '10 at 08:33
1

The closest I've been able to come is using a FUSE filesystem. It's pretty simple to use fusepy to write a custom passthrough filesystem, which can read environment variables when determining what real file to give. Of course, it only gets the environment variables of the process which mounted the passthrough system, so it's not as useful as it could be.

Perkins
  • 2,409
  • 25
  • 23
0

I encountered this exact same issue. On Linux (bash), I worked around it by doing the following:

First construct the command you would execute on the command line as a string. Quoting with " (this will allow any env variables to expand). Then use the eval command to execute the string it as if you typed it.

For example:

eval $(echo "ln -s $HOME myhomedir")

To break this into separate lines:

export MYCMD=$(echo "ln -s $HOME myhomedir")
eval $MYCMD
starball
  • 20,030
  • 7
  • 43
  • 238
user3675131
  • 3,185
  • 2
  • 11
  • 6
-3

Yes you can.

ln -s $HOME/file/or/folder newname

You can set your own variables and use them, too. Add in your .bashrc (or .bash_profile):

export $MYPATH=/your/path
kogakure
  • 3,777
  • 1
  • 16
  • 6
  • 2
    Check out thomasmalt's answer. What you've said is correct in and of itself, but the question's about having the environment variable stored in the link such that the environment is consulted each time the link is followed (which is not possible). – Tony Delroy Oct 08 '10 at 10:10
  • 1
    I don't think this response really understood the context of the question. – Sridhar Sarnobat Sep 12 '14 at 22:26