views:

199

answers:

6

I am somewhat confused how soft links work in unix. See the example.

% cd /usr/local/
% ls -la
total 6
drwxr-xr-x   2 root     root         512 Jan 19 15:03 .
drwxr-xr-x  41 root     sys         1024 Jan 20 16:24 ..
lrwxrwxrwx   1 root     root          38 Jan 19 15:03 java -> /otherDir/java/jdk1.6.0_17 **<- this is a soft link**

% cd java **<- move to the softlink**

% pwd
/usr/local/java **<- the current location, say LOCATION_A**

% cd /otherDir/java/jdk1.6.0_17/ **<-move to the location of the softlink**

% pwd
/otherDir/java/jdk1.6.0_17 **<- the new current location, say LOCATION_B**

Isn't this problematic that even though LOCATION_A is LOCATION_B, they have different paths?

Is there a command (other than pwd) that will give the real location of a file (not just how the user go there).

It seems to me like pwd is just the sum of a user's cd. NOT their current location.

+4  A: 

Try pwd -P. It's not "other than pwd" but it does the trick, at least on my bash 4.0.35 on Fedora 12. YMMV.

Update: Even works with sh, so it seems to be portable.

DaDaDom
+3  A: 

This behaves like this with a purpose. If you cd to /a/b/c/d and then cd to .. then you realistically expect to be in /a/b/c. If c happens to be a symbolic link (or symlink in unix terms - but not soft link) that takes you to /f/g/h, with the behaviour you would like to have you would end up in /f/g and then you (or any program) would not understand how it got there.

Bandi-T
That is the assumption built into the shells that implement this behaviour. It is not necessarily the assumption built into users of the shells until they are acquainted with the unexpected behaviour. Once acclimatized, it seems sort of natural; I'm still not wholly convinced and it isn't always what I want. IIRC, you can get the naive behaviour with '`cd ./..`'.
Jonathan Leffler
Sorry, it is not clear to me what your first "That" refers to.What do you think is the behaviour of the kernel for cases of `/a/b/c/..` where `c` is a symlink to `/f/g/h/`? I think it would be `/a/b/`, but not sure.
Bandi-T
No, the behavior of the kernel is that `/a/b/c/..` is `/f/g`. The "intuitive" behavior based on your access path is purely a shell invention, and only some shells. As far as I remember, `csh` doesn't have any trickery and thus behaves as the system natively would.
ephemient
+1  A: 

You can use readlink on the current working directory to get the true directory name:

readlink `pwd`
R Samuel Klatchko
A: 

realpath does what you want.

ennuikiller
+1  A: 

Normally, pwd should return /usr/local/java in the last line, if i understand your example. But some shells have a build in pwd command that tries to be more "intelligent" handling symlinks in the current working directory.

Try /bin/pwd, do you get other results?

Arne Burmeister
A: 

It is not possible to absolutely get your path under all circumstances. This is a bit odd, but a variation of this (plus chroot and setuid) is sometimes used for locking down a process.

$ mkdir -p /tmp/a/b
$ cd /tmp/a/b
$ rmdir /tmp/a/b
$ chmod 0 /tmp/a
$ rmdir /tmp/a
$ ls ..
ls: cannot open directory ..: Permission denied
$ ls -al
total 0
$ pwd -P
pwd: error retrieving current directory: getcwd: cannot access parent directories: No such file or directory
ephemient