How to tell if I'm actually in a symlink location from command line?

6,195

Solution 1

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

Solution 2

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.

Solution 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.

Solution 4

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.

Share:
6,195

Related videos on Youtube

Oliver Williams
Author by

Oliver Williams

Updated on September 18, 2022

Comments

  • Oliver Williams
    Oliver Williams almost 2 years

    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

    • Admin
      Admin over 7 years
    • Admin
      Admin over 7 years
      Some shells don't actually allow you to be inside a symlink. For example, the fish shell automatically resolves the symlink when you cd into it.
  • Oliver Williams
    Oliver Williams over 7 years
    yes, the -P flag was what I needed. Thanks
  • abligh
    abligh over 7 years
    Although I've learnt the hard way that readlink -f is not available on all Unices (e.g. not available on OS-X)
  • Dmitry Grigoryev
    Dmitry Grigoryev over 7 years
    You're not answering the question, you're dismissing it.
  • Anthony Geoghegan
    Anthony Geoghegan over 7 years
    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).
  • Arronical
    Arronical over 7 years
    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.
  • dougmc
    dougmc over 7 years
    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 ...
  • Peter Cordes
    Peter Cordes over 7 years
    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
  • Peter Cordes
    Peter Cordes over 7 years
    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
  • Peter Cordes
    Peter Cordes over 7 years
    @IMSoP: /bin/pwd -L just prints the $PWD environment variable. Without that, there's no way for a process to figure out its "logical" current working directory, because that isn't a real thing. It doesn't affect what you get from relative paths that start with ../, for example. strace /bin/pwd -P (the default) just makes a getcwd(2) system call. It doesn't trace up the .. links itself listing the directories to find matching inode numbers. It would be possible for the kernel to track "logical" paths, but it doesn't.
  • IMSoP
    IMSoP over 7 years
    @PeterCordes This answer talks about /bin/pwd and the shell doing different things, but other answers point out that both implementations have 2 modes, just different defaults. So if there really is a different algorithm used by the shell (which shell?) which mode is it for? Are there 3 different algorithms here, one for -L and two different ways of implementing -P? And when does it make a difference? I just tested the example given of ln -s . foo, and /bin/pwd and bash's builtin agree on the answer in both modes, as long as you specify the option rather than relying on the default.
  • Peter Cordes
    Peter Cordes over 7 years
    @IMSoP: AFAIK, nothing except shells and /bin/pwd look at the $PWD environment variable. IDK why /bin/pwd even has a -L option, except maybe for compatibility with the shell built-in. Unless checking $PWD is starting to catch on for use in file-selectors or something by programs started from the shell, it's still meaningless outside the shell. (But a child shell will inherit it, so it makes sense to have it in the environment).
  • Peter Cordes
    Peter Cordes over 7 years
    @IMSoP: no, I don't think there are multiple ways of implementing -P. They probably all call the POSIX getcwd() function, which (on Linux at least) is equivalent to traversing the .. links up to / and checking finding the directory you came from in each higher directory, but much more efficient.
  • IMSoP
    IMSoP over 7 years
    @PeterCordes Why does it have the option? For predictability: you need to be able to know that pwd will behave a certain way, regardless of whether it resolves to the shell implementation or the binary. So I guess historically, shell built-ins worked one way, and binaries the other, and then they standardised to both include both modes. I stand by my comment that as currently implemented, it's more useful to talk about the two modes and which is the default than to assert that there is a fundamental difference in how the shell built-in works.
  • Peter Cordes
    Peter Cordes over 7 years
    @IMSoP: I never asserted that. I just said that dougmc has it backwards, and the pwd -P path is the closest to the "correct" answer to where you are. (But really, your cwd doesn't have to have a name, e.g. if it's an unlinked directory. It still has an inode-number though, which is what the kernel really tracks).
  • Peter Cordes
    Peter Cordes over 7 years
    @IMSoP: I just checked, POSIX requires the pwd command to support -P and -L (use $PWD if it refers to the current directory and is canonical). Other than from a shell or shell script, it doesn't really make sense to run pwd, so I didn't see much of a use-case for it (and didn't realize the -L and -P options were standardized). But obviously since POSIX requires it, the coreutils implementation needs to do it so it can support use-cases like perl backticks or whatever.
  • dougmc
    dougmc over 7 years
    I don't have it backwards -- but yes, I was referring to the default usage of /bin/pwd and the default shell built-in pwd, which do indeed have different defaults (at least for most shells, regarding the shell version.) But yes, "pwd -P" would give a more "fundamental" answer than "pwd -L" I also really wasn't trying to be Linux specific ... this question and similar ones have been asked for longer than Linux has been around.