53

I would like an easy way to get the full path to a file. I currently type this:

echo `pwd`/file.ext

Trying to shorten it, I made a bash alias:

alias fp='echo `pwd`/'

But now if I type fp file.ext, there is a space that appears between the / and the file.ext.

Does such a command already exist, and I am missing it? If not, how would I go about creating such an alias or function in bash?

5 Answers 5

65

On linux systems, you should have readlink from the GNU coreutils project installed and can do this:

readlink -f file.ext

Debian/ubuntu systems may have the realpath utility installed which "provides mostly the same functionality as /bin/readlink -f in the coreutils package."

3
  • 1
    readlink -f (or realpath, which is an older utility kept for compatibility) will additionally expand all symbolic links, which is not necessarily desirable. Oct 23, 2010 at 22:42
  • 12
    fyi: does not work on macosx.
    – akira
    Nov 6, 2010 at 9:29
  • 4
    On my mac, I've installed coreutils using homebrew and it includes realpath. Sep 17, 2019 at 14:53
15

You can use:

realpath file.ext
7
  • 1
    I don't have that one. Where does that come from?
    – frabjous
    Oct 23, 2010 at 20:49
  • @frabjous: it's specific to Debian and derivatives, and will only be installed if you have requested it or a package that depends on it. Oct 23, 2010 at 22:42
  • I'm using Arch. That's not Debian based, but there's a package for it in the AUR anyway. Not sure it's worth installing if I already have readlink though.
    – frabjous
    Oct 23, 2010 at 23:58
  • Well, that's an option; or you may consider a function, see Gilles' answer. Anyway that depends on the real use you want to do with that (I'm curious).
    – cYrus
    Oct 24, 2010 at 0:16
  • @frabjous: You didn't specify what system you're on, but if it uses an Aptitude-based package manager (Debian, Ubuntu, Mint, etc.), you can type apt-cache search realpath to reveal that the coreutils and plain ol' realpath packages both contain it. You can then type sudo apt-get install realpath (or coreutils) to install it. Sep 5, 2018 at 8:01
12

From https://stackoverflow.com/a/3915420/5795941

This is the only way that is acceptable to me. Doesn't expand links like realpath and readlink and is the classical way of doing it that I've seen all over.

#! /bin/sh
echo "$(cd "$(dirname "$1")"; pwd -P)/$(basename "$1")"
1
  • 4
    This is the way to go when $1 can be either a relative or an absolute path Jun 16, 2020 at 1:16
10

Instead of the pwd command, use the PWD variable (it's in POSIX as well):

fp () {
  case "$1" in
    /*) printf '%s\n' "$1";;
    *) printf '%s\n' "$PWD/$1";;
  esac
}

If you need to support Windows, recognizing absolute paths will be more complicated as each port of unix tools has its own rules for translating file paths. With Cygwin, use the cygpath utility.

2
  • Maybe it's your choice but this function won't output the new line.
    – cYrus
    Oct 24, 2010 at 0:08
  • this approach has the advantage of using only shell-builtins, which is faster than to call external binaries. you should make this fact a little bit more clear.
    – akira
    Oct 24, 2010 at 8:49
4

to answer your question with what you use right now:

the alias expands at the position where you are typing right now. you typed:

% fp<SPACE>file.ext

this becomes

% echo `pwd`<SPACE>file.exe

you could use a function to avoid that:

function fp() {
    echo `pwd`/"$1"
}

you can use that as usual:

% fp file.ext
6
  • You need double quotes around variable and command substitutions: echo "`pwd`/$1" Oct 23, 2010 at 22:40
  • @Gilles: under what circumstances?
    – akira
    Oct 24, 2010 at 6:38
  • 2
    @akira: Always use double quotes unless you want the result of the expansion to be treated as a globbing pattern and the results of globbing to be split into words. Here you're building a single file name, so the double quotes are needed (try your function with a file called * in a directory containing other files). Oct 24, 2010 at 8:36
  • the '' is globbed by the shell (zsh in my case) and expanded before they hit the function. fp * yields /tmp/4cc3ea0c1b34b since thats the first paramete for the function. the other parameters would be the other files in the directory. as soon as i have a file called '' the function still works as expected, calling it with "*" or * or *
    – akira
    Oct 24, 2010 at 8:45
  • bash is the "bad" one here as it seems, bash yields what you are refering to.
    – akira
    Oct 24, 2010 at 8:46

You must log in to answer this question.