11

the basic idea is that I want to link to path that's relative to $HOME, rather than explicitly expand the $HOME variable, as I want to make sure the link works on multiple machines, e.g.,

when I do

ln -s ~/data datalnk

I want it to be directed to directory /home/user/data on one machine which has a user $HOME of /home/user, and to /home/machine/user/data on another machine which has a user $HOME of /home/machine/user/data.

I cannot create a symbolic link on the second machine using

ln -s /home/machine/user /home/user

because I don't have the permission to do that, and I cannot link relative paths as the two machines have different hierarchies of directories.

anyideas on possible ways to fix or circumvent this?

EDIT:

what I am really trying to accompanish is to make the same link work on two macihnes, where the targets have the same directories in terms of their relative path to $/HOME only, not their absolute path, and not their relative path to the link either.

nye17
  • 12,857
  • 11
  • 58
  • 68

3 Answers3

7

tl,dr it won't work

You can use an escaping mechanism such as single-quotes to get the ~ into the symbolic link:

> cd ~
> echo hello > a    
> ln -s '~/a' b

However, ~ is a shell expansion and is not understood by the filesystem (actually, to the filesystem it's "just another character"). This is a good thing -- want the file-system layer to know about environment variables, as ~ is generally determined by $HOME?

> ls -l b
lrwxrwxrwx    1 root     root             3 Oct 27 17:39 b -> ~/a
> ls b
ls: b: No such file or directory 

You could still "manually" look at said symbolic link entries (as done with ls -l), but that would have to be done in a non-transparent fashion by a program (think of a ".LNK" in Windows). As can be seen, the filesystem just doesn't understand ~.

Happy sh'ing.

2

First of all: It can't be done directly. Symbolic links are plain text files, no extensions are performed. If you can't formulate a fixed relative or absolute path to the place you are referring, you can't symbolically link to it.

You can build a script to put links to appropriate directories in appropriate places, but the best way depends on your application.

thiton
  • 35,651
  • 4
  • 70
  • 100
1

The only way to make symlinks dynamic in this way is to use a relative path instead of an absolute path. In other words, don't start your path with /.

For example:

cd
ln -s data datalnk

At runtime your app or script will need to refer to ~/datalnk or $HOME/datalnk.

You haven't really said what you're trying to accomplish, so I can't really tell whether I'm solving your problem or suggesting that you need to go at it a different way.

paulmelnikow
  • 16,895
  • 8
  • 63
  • 114
  • Thanks for the reponse. I have stated in the question that it seems that relative path doesn't work because the link and the target are generately having different relative path depth in between. what I am really trying to accompanish is to make the same link work on two macihnes, where the targets have the same directories in terms of their relative path to `$/HOME` only. – nye17 Oct 27 '11 at 17:42
  • But what are you actually trying to accomplish by this? Do you want to let the user choose where to put her/his data directory instead of forcing them to use a particular place like `~/data`? Where do you want to place this symlink, anyway? – paulmelnikow Oct 27 '11 at 18:02
  • it has nothing to do with other users. It's just that I am working on the same hg repository on two different machines that I don't have root privilege of, but I need to share the same data on the two machines without including them in the hg repo (too big to put in). I figured that I can simply link them in the hg repo while putting the links in a Dropbox directory to sync them outside of hg. Just to make the workflow on two machines seamless! – nye17 Oct 27 '11 at 18:08
  • Interesting. Are you running it under the same user account which contains the `~/data` folder? – paulmelnikow Oct 27 '11 at 18:26
  • unfortunately not, as I mentioned in the post, one is `/home/username1`, the other is `/home/machinename/username2`... – nye17 Oct 27 '11 at 18:28
  • And you're running it under more different users like `username3` and `username4`? – paulmelnikow Oct 27 '11 at 18:42
  • 1
    I don't understand why don't have your software simply expand `$HOME/data` on startup. In both cases you'll get the correct thing. It's exactly what `$HOME` is for. – paulmelnikow Oct 27 '11 at 18:49
  • that's definitely a solution! Thanks! – nye17 Oct 27 '11 at 19:17