3

I want to use the $PWD variable in a script, but I want it to be the hardware path without symlinks. I know about /bin/pwd and pwd -P, but those aren't variables.

I know that I can use:

setenv MYPWD `pwd -P`

But I remember there being another way to do it.

1
  • some shells support $(pwd -P) syntax, as opposed to back ticks, but I don't think (t)csh is one (or two) of them. Also, for why you shouldn't script in (t)csh, see: shlomifish.org/open-source/anti/csh Aug 16, 2013 at 4:12

3 Answers 3

5

In POSIX shells, after

cd -P .

$PWD will contain a symlink-free path.

In zsh, $PWD:A will expand to the symlink-free version of $PWD (works for any variable, not just $PWD).

In zsh, setopt chase_links, and in tcsh, set symlinks = chase, cause cd to make sure $PWD is symlink-free. However, that only works after the first cd. In zsh, cd . will make $PWD symlink free, but not in tcsh where you'd need cd "$cwd" (which is not guaranteed to work).

4
  • I'd rather not have to change the directory, I thought that there was a variable for this already. Aug 15, 2013 at 16:18
  • @BrianPostow - not that I've ever seen. There is $CWD, but it suffers the same issue.
    – slm
    Aug 15, 2013 at 16:20
  • @BrianPostow, cd ., by definition, doesn't change the directory. Aug 15, 2013 at 20:19
  • cd -P appears to, even though you are in the same physical dir, the logical path changes. You can use pushd and popd to counter this.
    – Jamie Pate
    Sep 22, 2014 at 19:39
1

To my knowledge there is no such variable provided by the environment that will guarantee that its value is the physical path and not a linked version.

Given this your options are limited to the choices that you've already mentioned plus the following alternative.

readlink

You can use the command readlink to get the physical directory/file that a symbolic link is pointing to:

Example

sample data:

$ ln -s /usr/bin/ack ack

$ ls -l |grep ack
lrwxrwxrwx   1 saml saml        12 Aug 15 11:48 ack -> /usr/bin/ack

physical location:

$ readlink ./ack
/usr/bin/ack
$ readlink /home/saml/ack 
/usr/bin/ack
$ readlink $HOME/ack
/usr/bin/ack

If the value you pass to readlink isn't a link it won't return anything. You can force it to return the canonical value by using the -f switch:

$ echo $PWD
/home/saml

$ readlink -f $PWD
/home/saml

References

2
  • A command doesn't help any. If I wanted a command I could just use /bin/pwd or pwd -P. I want a variable. Aug 15, 2013 at 16:18
  • 1
    No variable exists in the way that you want it. See @StephaneChazelas answer too. He'll tell you the same thing.
    – slm
    Aug 15, 2013 at 16:19
1

If you are using ksh93, there is a simple way to implement that variable. Just add this discipline function either at the beginning of your script or being sourced by it:

function PWDP.get
{
  .sh.value=$(pwd -P)
}

Then, you can just use the PWDP variable as you expect:

$ mkdir /tmp/foo
$ ln -s /tmp/foo /tmp/bar
$ cd /tmp/bar
$ echo $PWD
/tmp/bar
$ echo $PWDP
/tmp/foo

Edit, a "slightly" more complex solution trying to handle Stéphane Chazelas point:

function PWDP.get
{
    typeset p=$(pwd -P; echo .)
    .sh.value=${p%??}
}
4
  • as a small note: that doesn't work if the (physical) current directory ends in newline characters. Aug 21, 2013 at 13:49
  • @StephaneChazelas Answer updated with something to avoid this point but I have no doubt you'll find more issues with it ...
    – jlliagre
    Aug 21, 2013 at 20:59
  • Ouch. Yes, I've updated with a simpler and more reliable alternative. Hope you don't mind. Aug 21, 2013 at 21:08
  • @StephaneChazelas Much simpler indeed, thanks !
    – jlliagre
    Aug 21, 2013 at 21:10

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .