-   Programming (
-   -   bash: ln and relative paths (

tortle 11-30-2004 12:32 PM

bash: ln and relative paths

I just tried an 'ln -s' command in bash and got an unexpected result:


root@myhost:/usr/local/pkgs/mypkg# ln -s manual.html /usr/doc/mypkg/
root@myhost:/usr/local/pkgs/mypkg# cd /usr/doc/mypkg/
root@myhost:/usr/doc/mypkg# ls -l
total 1
lrwxrwxrwx  1 root root 12 2004-11-30 11:55 manual.html -> manual.html

'manual.html' ended up being a symbolic link to itself (?) rather than to the source that I thought I had specified.

I understand that the fix is to rm the existing link and then:


root@myhost:/usr/doc/mypkg# ln -s /usr/local/pkgs/mypkg/manual.html .
I did that and it worked. I am just wondering if anyone can provide insight as to why the relative paths that I specified in the original ln command were interpreted in the way that they were. TIA.

Hko 11-30-2004 12:50 PM

Yes. "ln" sees this as "create a symlink in /usr/doc/mypkg/". To which file it doesn't know.

You need to think the other way around:


cd /usr/doc/mypkg
ln -s /usr/local/pkgs/mypkg/manual.html .

Or, if you really want to do it with relative paths:

cd /usr/doc/mypkg
ln -s ../../local/pkgs/mypkg/manual.html .

tortle 12-01-2004 11:38 AM

Hi Hko:


"ln" sees this as "create a symlink in /usr/doc/mypkg/".
Yes; and that was the intent. The part that came out wrong is that, instead of:

"create a symlink at /usr/doc/mypkg/manual.html that points to /usr/local/pkgs/mypkg/manual.html "

ln understood:

"create a symlink at /usr/doc/mypkg/manual.html that points to /usr/doc/mypkg/manual.html"

The question is, "why?" The form of the ln command (according to the man page) is:

ln src [dest]
So the command that I am trying to construct, using absolute paths, is:


ln -s /usr/local/pkgs/mypkg/manual.html /usr/doc/mypkg/manual.html
I should be able to issue that command from anywhere and get the correct result.

If my current working directory is /usr/local/pkgs/, I should be able to omit that part from either the 'src' or 'dest' part. So (since that is where I was), I should be able to abbreviate the above to:


ln -s manual.html /usr/doc/mypkg/manual.html
But that is not how the command was interpreted. (I also omitted the filename in the [dest] part, but I think the above is enough to illustrate my question.)

I am trying to understand why. Is it because:

-- I am not understanding how relative paths work under *nix/Linux/slackware
-- ln treats relative paths in an unusual but correct way
-- the fact that I omitted the filename in the 'dest' part changes something (what?)
-- there is a bug in ln

or some other reason?


dustu76 12-02-2004 03:45 AM

From ln man on solaris:


-s Create a symbolic link.

If the -s option is used with two arguments, target
may be an existing directory or a non-existent file.
If target already exists and is not a directory, an
error is returned. source_file may be any path name
and need not exist. If it exists, it may be a file or
directory and may reside on a different file system
from target. If target is an existing directory, a
file is created in directory target whose name is
source_file or the last component of source_file. This
file is a symbolic link that references source_file.
If target does not exist, a file with name target is
created and it is a symbolic link that references
ln just creates the symlink entry in the target_directory. In case there is no such file in the target_directory, it is a symlink to itself.

ln has no business guessing what you "intended" to do. Try this:

ln -s somefile

where "somefile" doesnt exist in the current directory.

Then do "vi somefile" ...


LasseW 12-02-2004 05:49 AM

The dest is a file you create and you can expect exactly the behaviour you're describing, ie omitting the dir path puts the link in your default dir. The source is the contents of the link.

ln -s manual /my/dir/manual1
ln -s /some/dir/manual /my/dir/manual2
cd /tmp
ls -l /my/dir/manual1 # same as ls -l manual, ie /tmp/manual
ls -l /my/dir/manual2 # same as ls -l /some/dir/manual

ptyxs 05-10-2010 03:36 AM

Though I may be misguided, I feel that no real answer was given to tortle's posts in this thread.

The question might be asked again, no ?

I wonder whether the problem is perhaps just with the man page where I find :


ln [OPTION]... [-T] TARGET LINK_NAME (1st form)
ln [OPTION]... TARGET (2nd form)
ln [OPTION]... TARGET... DIRECTORY (3rd form)
ln [OPTION]... -t DIRECTORY TARGET... (4th form)
and later on :


In the 3rd and 4th forms, create links to each TARGET in DIRECTORY.
which, as I understand it, should permit the command issued by tortle (which seems to match 3rd form).

grail 05-10-2010 04:05 AM

Yes nice to provide the information, but instead of resurrecting an ancient thread, you should have just created your own as an information
only one. The issue you have here is that it will never (well very unlikely due to age) be marked as SOLVED, so your information will still be lost
to those users seeking this information as they will disregard any not marked as so.

ptyxs 05-10-2010 05:04 AM

I understand your point. However, tortle posts express the problem very clearly and I saw no reason to duplicate them.
Moreover, this thread is easily found on the Web, if you try a search on the ln command, and for that reason is still worth discussing, in my opinion.

grail 05-10-2010 05:50 AM

See I am not saying it can't be found, let us face it, you found it, however, the standard on this forum is that once a problem has a solution
it is marked with the word SOLVED. If you look in the search engine you will see that it is also one of the choices you can make, ie to restrict your
search to only those marked as SOLVED.
Assuming you do this first but do not find a result, when you open your search, most (not all of course) people will ignore anything that is over a certain
age as if it has not been SOLVED by now then it is more than likely redundant.

All times are GMT -5. The time now is 11:55 AM.