How do I cd up and down again with symlinks in bash?

Structure:

/base/
   +- somedir/
   +- symlink/  -> /some_other_dir

This command (in addition to my Makefiles) fails:

cd /base/symlink
ls ../somedir

Bash complains that ../somedir does not exist. Likewise, my makefiles in some_other_dir that reference ../somedir fail. However, cd .. works just as expected. Can I have my shell act with regards to the logical structure?

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

.. is a directory entry in the current directory. It is a hardlink to the directory one level up. /base/symlink/.. is actually the same file as /some_other_dir/.., and it is / (unless some_other_dir is itself also a symlink to somewhere else).

In most shells, cd treats .. specially, that is instead of treating it as the .. directory entry, occurrences of .. are interpreted by cd (and not by the system’s pathname resolution) as removing one level of directory.

As an example, in cd a/b/.., the shell does a chdir("a") instead of doing a chdir("a/b/.."). To get the latter, you need to do cd -P a/b/...

It’s important to realise that it only applies to cd (and only in some shells), (IMO, a misfeature), not to ls or vi or anything else (unless that anything else is a script of those shells that passes those paths to cd without -P).

In those shells where cd does that logical interpretation of .., the pwd builtin and the $PWD variable contain the logical current directory instead of the real (physical) one, that is one with possibly symlink directory components. Similarly, you can use pwd -P to get the physical working directory.

Now, if you want to do

cd /A/b
anything-but-cd ../c

And actually mean:

anything-but-cd /A/c

Regardless of whether /A/b was a symlink or not, you could do instead:

anything-but-cd "$(dirname -- "$PWD")/c"

or

anything-but-cd "${PWD%/*}/c"

Or with zsh:

anything-but-cd $PWD:h/c

To remove 3 /*s off the end of $PWD:

anything-but-cd "${PWD%/*/*/*}/c" # POSIX
anything-but-cd $PWD:h:h:h/c      # zsh


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x