Get the canonical path for a command

5,700
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.

Share:
5,700

Related videos on Youtube

mythic
Author by

mythic

Software engineer from Slovenia

Updated on September 18, 2022

Comments

  • mythic
    mythic almost 2 years

    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:

    /home/user/Documents/sleep
    

    What I actually want is /bin/sleep

    • VocalFan
      VocalFan about 8 years
      Does sleep (either a file or a symlink) actually exist in that directory?
    • mythic
      mythic about 8 years
      No, they are mostly commands (not in the script directory)
  • Stéphane Chazelas
    Stéphane Chazelas about 8 years
    [ ! -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
    Stéphane Chazelas about 8 years
    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).