34

Suppose I have a folder:

cd /home/cpm135/public_html

and make a symbolic link

ln -s /var/lib/class .

Later, I'm in that directory:

cd /home/cpm135/public_html/class

The pwd is going to tell me I'm in /home/cpm135/public_html/class

Is there any way to know that I'm "really" in /var/lib/class ? Thanks

2

4 Answers 4

57

Depending on how your pwd command is configured, it may default to showing the logical working directory (output by pwd -L) which would show the symlink location, or the physical working directory (output by pwd -P) which ignores the symlink and shows the "real" directory.

For complete information you can do

file "$(pwd -L)"

Inside a symlink, this will return

/path/of/symlink: symbolic link to /path/of/real/directory
4
  • 1
    yes, the -P flag was what I needed. Thanks Dec 18, 2016 at 12:49
  • 6
    To also answer the question in the title, just use test "$(pwd -L)" = "$(pwd -P)" && echo No symlinks (or replace && echo No symlinks with || echo Symlinks).
    – user
    Dec 18, 2016 at 14:45
  • 1
    This answers the question perfectly without the need to echo. If the question was 'How do I display a message if I'm in a symlinked directory?" then echo would be required.
    – Arronical
    Dec 19, 2016 at 11:57
  • file "$(pwd)" only works if the symlink is the last directory component. It doesn't detect the OP's symlink when CDed to /home/cpm135/public_html/class/foo/bar. I'm not aware of anything that prints info for all the symlinks in a pathname, but you can also use realpath ., which I think is equivalent to pwd -P Dec 20, 2016 at 2:25
17

Note that pwd is actually a shell built-in. Depending on your shell and its configuration, results may change. For a more portable solution, you should use /bin/pwd. Snippet from manual page:

NAME
       pwd - print name of current/working directory

SYNOPSIS
       pwd [OPTION]...

DESCRIPTION
       Print the full filename of the current working directory.

       -L, --logical
              use PWD from environment, even if it contains symlinks

       -P, --physical
              avoid all symlinks

       --help display this help and exit

       --version
              output version information and exit

       If no option is specified, -P is assumed.

       NOTE:  your  shell  may  have  its  own  version of pwd, which usually supersedes the version described here.  Please refer to your shell's documentation for
       details about the options it supports.

In general, you can resolve the full canonical path of any file/directory using readlink -f. readlink -f . works similar to pwd -P.

1
  • 2
    Although I've learnt the hard way that readlink -f is not available on all Unices (e.g. not available on OS-X)
    – abligh
    Dec 18, 2016 at 17:55
3

You really are in /home/cpm135/public_html/class -- that's the only correct answer to the question of "what's my current working directory".

When you refer to /var/lib/class ... that's not really about where you are, but more about what path you used to get there.

When you run /bin/pwd, it figures out your current working directory by looking at the . and .. directories (the ones listed at the top of ls -la), working out which directory in .. matches up with . and then working backwards until .. and . refer to the same directory. Once it's done all that, it knows what your current working directory is.

When you run the pwd shell built-in, it doesn't follow this procedure (though it might do some of it if needed) -- instead, it remembers the path that you took to get here. So each time you do a cd command, your shell remembers that as part of the path to get where you are now, and pwd prints out what it has calculated based on all the cd commands you've done -- which may or may not be your actual working directory.

Things can get really weird when you do a ln -s . foo and keep cding into foo -- /bin/pwd will say you're still in the same directory, but the shell builtin pwd will say you're in /foo/foo/foo/foo/foo/foo -- even though no such directory even really exists. (That said -- you probably can cd into it.)

Another source of confusion there is if directories are renamed. /bin/pwd will then pick up on the change immediately, but the built-in pwd won't until you do something that tells it that the old directory name doesn't matter.

13
  • 1
    You're not answering the question, you're dismissing it. Dec 19, 2016 at 9:47
  • 4
    While this doesn't answer the question directly, I think it's a useful post for understanding the difference between the shell's pwd builtin and /bin/pwd and explaining how the stand-alone version provides more useful information (which can answer the original question). Dec 19, 2016 at 10:18
  • 1
    These differences all boil down to the -P and -L options mentioned by other answers. In short, some implementations default to one, some to the other. On the Centos system I have to hand, bash's builtin is defaulting to logical, and /bin/pwd is defaulting to physical, but both accept both command-line options and agree on the result when they are given.
    – IMSoP
    Dec 19, 2016 at 10:36
  • 1
    The question is based on an incorrect premise -- 'is there any way to know that I'm "really" in /var/lib/class?' That said ... by explaining what that really means, it helps him understand what he's really looking for. The pwd -P and -L options had already been mentioned ...
    – dougmc
    Dec 19, 2016 at 15:41
  • 1
    You have your argument backwards. ls .. will show the contents of /var/lib, not /home/cpm135/public_html. cd .. is special: the shell does special tracking of "how you got there" and doesn't actually make a chdir("..") system call. As far as the kernel is concerned, your shell's current working directory (/proc/self/cwd) is just a mountpoint:inode pair. It's like an open file descriptor on the directory, which is why renaming the directory doesn't break your shell. (cd . to update the shell's $PWD variable). You're making a useful point, so I'd upvote this when fixed Dec 20, 2016 at 2:34
1

Essentially you are asking if there is to show actual path of the current working directory. Well, there is with python and os.getcwd() function

What you see below is a small test from within "VirtualBox VMs" directory located in my home directory. In reality, it's a symlink to a different directory located on different hard drive, mounted at /mnt/HDD.

bash-4.3$ file "$(pwd)"
/home/xieerqi/VirtualBox VMs: symbolic link to /mnt/HDD/VirtualBox VMs/
bash-4.3$ python -c 'import os; print os.getcwd()'
/mnt/HDD/VirtualBox VMs

As you can see, python's os.getcwd() resolves the real path of the directory, not the path of symlink.

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.