tags:

views:

120

answers:

4

Question: is there a simple sh/bash/zsh/fish/... command to print the absolute path of whichever file I feed it?

Usage case: I'm in directory /a/b and I'd like to print the full path to file c on the command-line so that I can easily paste it into another program: /a/b/c. Simple, yet a little program to do this could probably save me 5 or so seconds when it comes to handling long paths, which in the end adds up. So it surprises me that I can't find a standard utility to do this — is there really none?

Here's a sample implementation, abspath.py:

#!/usr/bin/python
# Author: Diggory Hardy <[email protected]>
# Licence: public domain
# Purpose: print the absolute path of all input paths

import sys
import os.path
if len(sys.argv)>1:
    for i in range(1,len(sys.argv)):
        print os.path.abspath( sys.argv[i] )
    sys.exit(0)
else:
    print >> sys.stderr, "Usage: ",sys.argv[0]," PATH."
    sys.exit(1)
+2  A: 

Try realpath.

~ $ realpath .bashrc
/home/username/.bashrc
honk
+1, very nice program. But note that it is an external command (not a shell built-in) and may not be present in every system by default, i.e. you may need to install it. In Debian it resides in a separate package with the same name.
Roman Cheplyaka
Exactly what I was looking for, thanks! Only question is why I couldn't find this myself...
dhardy
True, it isn't a built-in, but that's usually only an issue when using locked-down university computers.
dhardy
+1  A: 
#! /bin/sh
echo `cd \`dirname $1\`; pwd`/`basename $1`
dogbane
Don't forget to quote all the stuff. If you don't understand why, try your program on a file `a b` (two spaces between a and b, SO eats one of them).
Roman Cheplyaka
+1  A: 

Try readlink which will resolve symbolic links:

readlink -e /foo/bar/baz
Dennis Williamson
I would rather use '-f' instead of '-e' so that we can see absolute path of a nonexistent file.
hluk
+1  A: 

If you don't have readlink or realpath utilities than you can use following function which works in bash and zsh (not sure about the rest).

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

This also works for nonexistent files (as does the python function os.path.abspath).

Unfortunately abspath ./../somefile doesn't get rid of the dots.

hluk
Looks portable to me. On the other hand, will break for example on a filename containing a newline.
Roman Cheplyaka
Yup, you are right. I've removed the grep completely.
hluk
To improve further, replace `echo "$1"` with `printf "%s\n" "$1"` (same with the second echo). `echo` may interpret backslashes inside its arguments.
Roman Cheplyaka
Again, you're right! Really, the behavior of echo command in zsh is different from bash.
hluk
Strictly speaking, under POSIX behaviour of echo is undefined if arguments contain backslashes. However, it is defined under XSI extension (namely, echo should interpret the escape sequences). But both bash and zsh are soo far even from POSIX compliance...
Roman Cheplyaka
Sorry, but I don't see the point. I already provided an answer as a script with more features that this and it doesn't need to be used within a shell script.
dhardy