I'm writing a script that needs canonical path of certain commands. Since there could be symbolic links pointing to the actual commands, I use readlink -f to get the canonical path. But I'm not getting what I actually want with readlink -f, I'll explain with the following example:

Let's say my current directory is: /home/user/Documents If I try to get a path of sleep with readlink -f I get this:


What I actually want is /bin/sleep

  • Does sleep (either a file or a symlink) actually exist in that directory? – JigglyNaga May 20 '16 at 12:03
  • No, they are mostly commands (not in the script directory) – mythic May 20 '16 at 12:58
readlink -f "$(type -P sleep)"

or if you're performance-conscious:

cpath="$(type -P sleep)"; [ ! -L "$cpath" ] || cpath="$(readlink -f "$cpath")"

Using readlink -e (existing) instead of readlink -f can save you from this kind of accident where you operate on a nonexisting file.

The second example assumes the path returned by type -P is canonical, which means it assumes your path doesn't have non-canonical components.

| improve this answer | |
  • 3
    [ ! -L "$cdpath" ] is not a guarantee that the path is canonical or even absolute. The path could still be relative, and another of the components but the last may be a symlink. – Stéphane Chazelas May 20 '16 at 12:06
  • 3
    Beware which has a number of issues. The standard command would be command -v (though would return the command name for those commands that are builtin). – Stéphane Chazelas May 20 '16 at 12:07

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.