24

I have debian squeeze amd64. My current shell is bash. If I write the following in my terminal, it works:

$ uname -a
Linux core 2.6.32-5-amd64 #1 SMP Fri May 10 08:43:19 UTC 2013 x86_64 GNU/Linux
$ echo $SHELL
/bin/bash                                                                                                                                                                                     
$ echo $(realpath test.sh)                                                                                                                                                     
/home/ffortier/test.sh

My test.sh file looks like this:

#!/bin/bash
echo $(realpath "$1")

If I try to execute the following, I get an error

$ ./test.sh test.sh 
./test.sh: line 2: realpath: command not found

How can I use the realpath command within a bash file?

Additional Information

$ type -a realpath
realpath is a function                                                                                                                                                                        
realpath ()                                                                                                                                                                                   
{                                                                                                                                                                                             
    f=$@;                                                                                                                                                                                     
    if [ -d "$f" ]; then                                                                                                                                                                      
        base="";                                                                                                                                                                              
        dir="$f";                                                                                                                                                                             
    else                                                                                                                                                                                      
        base="/$(basename "$f")";                                                                                                                                                             
        dir=$(dirname "$f");                                                                                                                                                                  
    fi;                                                                                                                                                                                       
    dir=$(cd "$dir" && /bin/pwd);                                                                                                                                                             
    echo "$dir$base"                                                                                                                                                                          
}           
9

Is realpath a actual command or a script? I would check to see where it is coming from.

$ type -a realpath

I'm not familiar with this tool, and so it's likely not part of your normal distribution, perhaps it's installed in a non-standard location which isn't present on Bash's $PATH but is within your login environment's $PATH.

In any event, the above type command will show you where the command is coming from, at which point you can alter the method you're calling it in your script like so:

echo $(/path/to/realpath test.sh)

Or amend your script's $PATH so that it also includes this non-standard location.

Functions in the shell

Much of your environment does not get called when you invoke a shell script. If you think about this, this makes a lot of sense, since you generally don't want scripts to have all the additional baggage that a user's environment may have.

You can either determine which source file is providing this function and either source it, or simply instruct Bash to incorporate your login environment.

#!/bin/bash -l
echo $(realpath "$1")
  • It's a function, see edit – Francis Nov 13 '13 at 20:15
  • @Francis - yeah the functions are not included when you invoke your script. You'll need to source them if you want them to come along. Find out which file is providing the function and source it. If you just want your whole env. then amend your call to bash, #!/bin/bash -l. – slm Nov 13 '13 at 20:18
  • How can I find where this function comes from? – Francis Nov 13 '13 at 20:19
  • 1
    @mikeserv - thanks, when I wrote this up I was still using Fedora 14 which did not include realpath. My Fedora 19 system does now include this tool. Also notice the OP was using a Debian w/ 2.6 kernel, so his system too would've been missing realpath given its age. – slm May 5 '14 at 2:32
  • 1
    @mikeserv - yeah I was surprised, this is an old-ish Q now, but the info about command was still useful to me. It's a more portable way to do what I was showing across POSIX shells. – slm May 5 '14 at 2:38
26

There are at least two programs called realpath:

  • An old program from back when GNU coreutils didn't include readlink -f. It is now deprecated in favor of readlink -f, so many distributions have stopped carrying it.
  • The realpath program introduced in GNU coreutils 8.15. This is too old to be in Debian squeeze or even wheezy; at the time of writing, Debian unstable doesn't ship it either. This program is very close to readlink -f.

For some reason, you have a shell function which partly emulates the behavior of realpath. This emulation is partial: if you call it on a symbolic link, it doesn't follow the symbolic link.

Since this is a shell function, presumably loaded from or via .bashrc, it's only available to code running in your interactive shell. If you want it to be available to other programs, assuming you're running Linux, create a script that emulates realpath:

#!/bin/sh
readlink -f -- "$@"

(This doesn't emulate realpath's rarely-used command line options.)

  • 2
    I cannot find any evidence in the coreutils git repo that the realpath program is considered deprecated by coreutils, or that it is not built by default. So Debian must be removing it. – Kaz Apr 27 '14 at 14:36
  • @Kaz Oh, well, just to complicate matters, coreutils recently (8.15) introduced a realpath binary, which is close but not exactly identical to readlink -f. Debian stable carries 8.13. Debian unstable chose to keep the legacy program. – Gilles Apr 27 '14 at 17:18
  • It wasn't that recently - it was Jan 2012. savannah.gnu.org/forum/forum.php?forum_id=7076 – mikeserv Apr 27 '14 at 17:27
  • 1
    @mikeserv Far too recent for the distribution in the question (Debian squeeze). Even too recent for the current Debian stable. – Gilles Apr 27 '14 at 17:29
  • That's kinda scary. How old is their openssl? – mikeserv Apr 27 '14 at 17:30
8

It works only in shell, because script file has different scope and doesn't have access to your local functions and aliases defined in your rc files. And realpath command actually doesn't exist in your system.

So either install realpath from the package, define your own function (as part of the script, check some examples) or source the rc file in your script where it's defined (e.g. . ~/.bashrc).


Here are the steps to install realpath if it's not present:

  • Ubuntu: sudo apt-get install coreutils
  • OS X: brew install coreutils

Ubuntu & Debian

On Debian or Ubuntu it seems the realpath should be installed by default. I've checked in the recent Debian 8 (Jessie) and it seems to have coreutils installed by default.

Tested using fresh VM images:

$ vagrant init debian/jessie64 && vagrant up --provider virtualbox && vagrant ssh
$ vagrant init ubuntu/vivid64 && vagrant up --provider virtualbox && vagrant ssh

Then in VM:

$ type -a realpath
realpath is /usr/bin/realpath

Instead of realpath, you can also use readlink -f file (or greadlink) provided by coreutils package as well.

5
$ sudo apt-get install realpath

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.