6

In my home directory ~, I issued

ln -s Subfolder1/Subfolder2/Subfolder3

I then have a soft-linked folder Subfolder3 in my home directory.  When I pushd into it, both pwd and dirs show my current working directory (cwd) to be /home/My.User.Name/Subfolder3.  My bash prompt also contains the cwd, which displays as ~/Subfolder3.

I recall that many years ago, after a cd or pushd into a symbolically linked folder, the full path ~/Subfolder1/Subfolder2/Subfolder3 would be shown by pwd, dirs, and in the bash prompt. Is it a simple setting to get that behaviour back?

3 Answers 3

12

The documentation (man bash, search for symbolic) shows you can either handle this each time you use cd and pushd, or by setting a global option

cd -P path/through/symlink
pushd -P path

set -P

This global option switches bash to use real paths everywhere

0
2

As an alternative to FeRD’s answer, for one-off dereferencing of the current working directory, you can use pwd -P.  Unfortunately, it doesn't work for dirs.

For a longer-term solution, you could define a shell function:

cd() {
    command cd "$@"  &&  command cd "$(pwd -P)"
}

(Put this into your .bashrc file.)  This will cause the cd function to run the cd built-in command, and, if it succeeds, to get the absolute pathname and cd to that.  This will cause $PWD to be set to that path, and will cause it to be shown in the shell prompt.

Under rare conditions, the second command cd might fail.  In this case, you should still be in the directory you intended to cd into, but you will still see the symlink name (and the cd function may show you an error message, even if the (first) cd succeeded).  Conceivably, the second cd might take you out of the directory you want to be in, but I can’t think of a scenario in which that could happen.

3
  • 1
    Thanks, G-Man. I think I'm going to stick with the simpler solutions. There was a time when I went to town with aliases, and I have leanings toward a simpler life these days. Feb 12 at 3:26
  • I fell out of the habit with defining aliases / shell functions when I realized they fell into two categories: (1) aliases I never actually remembered to use after defining them; (2) aliases I got in the habit of using, which then screwed me up whenever I was logged in to an account/system where they weren't defined.
    – FeRD
    Mar 12 at 11:30
  • Though it strikes me, G-Man, that your cd function could use command cd "$(realpath "$@")" to avoid both the double-cd and the temporary transit into the symlinked version of the path. (The bare, nested double-doublequotes freaks me out, but it tests correct.) Defining pushd() as command pushd "$(realpath "$@")" causes dirs to contain a valid "physical dir stack", as well.
    – FeRD
    Mar 12 at 11:50
2

For one-off dereferencing, there's also the recommended realpath utility:

[ferd ~]$ cd /var/tmp/
[ferd tmp]$ ln -s /home/ferd/Videos MyVideos
[ferd tmp]$ cd MyVideos
[ferd MyVideos]$ pwd
/var/tmp/MyVideos
[ferd MyVideos]$ realpath .
/home/ferd/Videos

Having your directories automatically realpath-ed is usually a shell option; in zsh it's CHASE_LINKS.

It's not the default because it greatly confuses things like directory recursion and .. semantics. (In ways that I believe can even be considered security vulnerabilities.)

You should carefully consider whether it's really the best configuration for your interactive sessions. (In my experience, it seems like it is... until you try it.)

4
  • 2
    The default behaviour (of shells not canonicalizing paths) can also bite you. For example ls .. uses the "physical" .. because it's not a shell builtin, so it's not always the same as (cd ..; ls). But as far as security, if you mean scripts that assume cd foo && cd .. will restore you to the original CWD, yeah that's a good thing. Otherwise a script that used that instead could be tricked into doing something the sys admin didn't want, so careful scripts would have to avoid it in favour of pushd / popd or saving $PWD Feb 11 at 17:17
  • @PeterCordes Oh, sure, .. semantics are already strained by directory symlinks — heck, even ls ./MyVideos/../ from /var/tmp/ in my example will list the contents of /home/ferd/ instead of /var/tmp/, and there's no way around that. But at least cd MyVideos; ls; cd .. will list the contents of /home/ferd/Videos/ and then land you back in /var/tmp/. Turning on symlink dereferencing quickly reveals just how often we type things like that and just expect them to DTRT, and how much it violates the Principle of Least Astonishment to mess with that expectation.
    – FeRD
    Feb 11 at 17:36
  • 1
    @FeRD: That's quite handy, and much more descriptive than command switches. For now, I set -P (in Bash), but I can see when realpath will be preferrable. Thanks! Feb 12 at 3:24
  • I should mention (regarding Peter's earlier point about admin scripts/tasks) that I actually use zsh with the AUTO_PUSHD option turned on, so that every cd is processed as a pushd. Which means I always have a full history of my working directories available. ...But even so, I still found CHASE_LINKS mode confusing enough that I ended up disabling it.
    – FeRD
    Feb 13 at 5:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.