8

The answers linked to don't actually answer my question the way the accepted answer does. Google only points at the other answers, which are not actually answers to this particular question.


When following a symbolic link to a directory, the bash shell kind-of tries to make the illusion that the symbolic link is a real directory. However, there are many cases where this breaks down. For example, consider that I might have:

/usr/local/src/project-a-1.0/
/usr/local/src/project-b-2.2/

then, I have a symlink in my home directory:

ln -s /usr/local/src/project-a-1.0 ~/project

Now, I want to short-cut to work with project-a:

cd ~/project

So far, so good -- but bash pretend that I'm actually in ~/project, not in the actual working directory. It even pretend when using the pwd built-in, but of course not when using the /bin/pwd executable.

Now, if I want to check out a file in project-b, I might want to try vim ../project-b<TAB> to try to make command completion work. However, bash refuses to complete this, because it thinks that .. is the directory containing user homes.

However, if I type in vim ../project-b-2.2/somefile.txt then that works fine, which is what I expected.

Symlinks are not directories, and all kinds of inconveniences and even errors happen because of this mis-feature in bash. I've tried to search for an option to turn this off, but all the google and superuser hits are just about "how to I manually resolve a link path" -- that's not what I want here; I want bash to stop trying to emulate a file system on top of my file system, poorly. Surely, there exists some option that will put correctness in front of illusion?

The "similar questions" popup pointed at two other questions that Google already sent me to; both of them require me to pass the "-P" option to pwd or cd or even recommend using readlink to figure out the symbolic link target. That's not at all what I'm interested in. I want the built-in pwd and the shell prompt $PWD to match the physical output of the getcwd() system call; those questions don't talk about that at all.

F1Krazy
  • 103
  • 4
Jon Watte
  • 825
  • 2
  • 10
  • 16
  • You have to admit that the accepted answer for https://superuser.com/questions/1312196/linux-symbolic-links-how-to-go-to-the-pointed-to-directory does answer your question :) – bers Apr 05 '22 at 14:45
  • This question has appeared in the reopen queue multiple times. It has failed to achieve the required votes to be reopened due to the meta-commentary that it contains. Alas in it's current form I was forced to vote to NOT reopen it. I would also argue that [this](https://superuser.com/questions/1312196/linux-symbolic-links-how-to-go-to-the-pointed-to-directory) answer makes the same suggestion as the answer you received. From the duplicate: "You can adjust the default behavior of cd builtin by set -P (cd acts as cd -P) and set +P (cd acts as cd -L). See help set for details." – Ramhound Apr 17 '22 at 15:04
  • This is the subject of [a meta question](https://meta.stackexchange.com/questions/378000/how-to-un-duplicate-a-question-thats-obviously-not-a-duplicate). – Peter Mortensen Apr 18 '22 at 09:30

2 Answers2

10

There is a shell-wide option for this:

-P

If set, do not resolve symbolic links when performing commands such as cd which change the current directory. The physical directory is used instead. By default, Bash follows the logical chain of directories when performing commands which change the current directory.

For example, if /usr/sys is a symbolic link to /usr/local/sys then:

$ cd /usr/sys; echo $PWD
/usr/sys
$ cd ..; pwd
/usr

If set -P is on, then:

$ cd /usr/sys; echo $PWD
/usr/local/sys
$ cd ..; pwd
/usr/local

So this should get you the behaviour you want:

set -P
muru
  • 1,195
  • 9
  • 33
-2

This may not be what you want to hear, but I would argue that the idea of a canonical path to a file is flawed.

First, if you create a hard link to an existing file there are now literally two distinct paths to the same file:

$ cd "$(mktemp --directory)"
$ touch foo
$ ln foo bar
$ ls --inode 
1223418 bar  1223418 foo

There is no "original" among these two, and they keep the same metadata except for their name:

$ touch --date='2001-02-03 04:05:06.789' bar
$ ls -lA
total 0
[…] Feb  3  2001 bar
[…] Feb  3  2001 foo

Second, there are many ways to refer to a file, depending on context:

  • Relative paths to a hard or symbolic link
  • Absolute paths (multiple, as seen above) to a hard or symbolic link
  • file:///absolute/path/to/file or other protocols

All of these are useful in different contexts.

Third, Bash isn't "pretending" anything; there is no illusion, you really are in that directory. The fact that it is a symlink should be transparent to almost all actions you would ever do with it.

Fourth, symlinks have nothing to do with Bash; they are a filesystem feature, not related to any shell, terminal or even OS. And every major filesystem has them, so trying to ignore them is probably going to hinder rather than help you.

Finally, any tool which treats symlinks specially without being explicitly told to do so should be fixed, because it has a bug.

l0b0
  • 7,171
  • 4
  • 33
  • 54
  • 1
    Re: Third: Bash **is** pretending. The result of [the `getcwd()` function](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getcwd.html) wouldn't include any symbolic links in it, so bash has to keep track of the path with symlinks in it separately. If it were actually taking the output of `getcwd()` and then going to its parent, you would get the behaviour OP is asking for. – muru Apr 23 '18 at 05:54
  • That isn't pretending, that's just how one specific function works. `pwd` prints the symlinked directory and `$PWD` contains the symlinked directory. – l0b0 Apr 23 '18 at 07:07
  • of course they do, they're all implemented by bash and so the same internal state is available to them. Try the external `pwd` command. – muru Apr 23 '18 at 07:27
  • Thank you for the answer. It turns out, I am quite aware of how the UNIX file system works. That's why I don't like how bash is pretending. And, yes, it's pretending! When "ls .." doesn't show the same thing as "cd ..; ls" then the shell has stopped helping and is hurting. I downvote your answer because I fundamentally disagree with your statements; I think they are factually wrong. – Jon Watte Apr 24 '18 at 16:09