- How do I get the absolute directory of a file in Bash?
- 7 Answers 7
- Get Absolute File Path in Linux
- Use readlink to get file path
- Use realpath to get full file path
- Use the find command to get the absolute file path
- Print full path with the ls command
- Conclusion
- How to get the full path of a file in bash?
- 5 Answers 5
- Get absolute path of files using ‘find’ command
How do I get the absolute directory of a file in Bash?
I have written a Bash script that takes an input file as an argument and reads it.
This file contains some paths (relative to its location) to other files. I would like the script to go to the folder containing the input file, to execute further commands. In Linux, how do I get the folder (and just the folder) from an input file?
Are you giving the full path to the input file or just the path relative to the current working directory?
7 Answers 7
readlink -f relative/path/to/file
To get the directory of a file:
dirname relative/path/to/file
You can also combine the two:
dirname $(readlink -f relative/path/to/file)
If readlink -f is not available on your system you can use this * :
function myreadlink() < ( cd "$(dirname $1)" # or cd "$" echo "$PWD/$(basename $1)" # or echo "$PWD/$" ) >
Note that if you only need to move to a directory of a file specified as a relative path, you don’t need to know the absolute path, a relative path is perfectly legal, so just use:
cd $(dirname relative/path/to/file)
if you wish to go back (while the script is running) to the original path, use pushd instead of cd , and popd when you are done.
* While myreadlink above is good enough in the context of this question, it has some limitation relative to the readlink tool suggested above. For example it doesn’t correctly follow a link to a file with different basename .
Get Absolute File Path in Linux
Here are different ways to get the absolute file paths in Linux command line.
You can get the full path of a directory with the pwd command:
But how do you get the absolute path of a file in Linux?
There are several ways to print the full path of files:
- readlink
- realpath
- find
- combining ls and pwd
Let me show you these commands one by one. But before that, I suggest brushing up on the basics of the absolute and relative path concept first.
Use readlink to get file path
The purpose of the readlink command is to resolve symbolic links. You can use it to display the full path of a file like this:
[email protected]:~$ readlink -f sample.txt /home/abhishek/sample.txt [email protected]:
Use realpath to get full file path
The realpath command is used for resolving the absolute file names. Among other uses, it can show the full path to a file.
Take a look at this example:
[email protected]:~$ realpath sample.txt /home/abhishek/sample.txt [email protected]:~$
If you use it with a symbolic link, it will show the real path of the original file. You can force it to not follow the symbolic link:
Here’s an example where it showed the full path to the source file by default and then I forced it to show the symbolic link, not its original file.
[email protected]:~$ realpath linking-park /home/abhishek/Documents/ubuntu-commands.md [email protected]:~$ realpath -s linking-park
Use the find command to get the absolute file path
Here’s the thing with the find command. Everything is relative to the directory you give it for search location.
If you give it . it will show the relative path. If you give it the absolute path of the directory, you’ll get the absolute path of the files you are searching for.
Use the command substitution with the find command like this:
You can run it to find the full path of a single file:
[email protected]:~$ find $(pwd) -name sample.txt /home/abhishek/sample.txt
Or, you can use it with a bunch of files matching a certain pattern:
[email protected]:~/Documents/eBooks$ find $(pwd) -name "*.pdf" /home/abhishek/Documents/eBooks/think-like-a-programmer.pdf /home/abhishek/Documents/eBooks/linux-guide.pdf /home/abhishek/Documents/eBooks/absolute-open-bsd.pdf /home/abhishek/Documents/eBooks/theory-of-fun-for-game-design.pdf /home/abhishek/Documents/eBooks/Ubuntu 1804 english.pdf /home/abhishek/Documents/eBooks/computer_science_distilled_v1.4.pdf /home/abhishek/Documents/eBooks/the-art-of-debugging-with-gdb-and-eclipse.pdf
Print full path with the ls command
Now this one is a bit tricky and messy.
You can use the environment variable PWD with ls command like this to display the files and directories with their absolute path:
You get an output like this:
[email protected]:~/test$ ls -ld $PWD/* -r--rw-r-- 1 abhishek abhishek 0 Jul 27 16:57 /home/abhishek/test/file2.txt drwxrwxr-x 2 abhishek abhishek 4096 Aug 22 16:58 /home/abhishek/test/new
However, to print the full path of a file with the ls command, you’ll have to use it like this:
Not the cleanest solution but it works.
[email protected]:~$ ls -l $PWD/sample.txt -rw-r--r-- 1 abhishek abhishek 12813 Sep 7 11:50 /home/abhishek/sample.txt [email protected]:~$
Conclusion
I showed four different ways to get the full file path in Linux. The find and ls commands are common while realpath and readlink are hardly known to many Linux users. It’s always good to learn new things, isn’t it?
How to get the full path of a file in bash?
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
On linux systems, you should have readlink from the GNU coreutils project installed and can do this:
Debian/ubuntu systems may have the realpath utility installed which «provides mostly the same functionality as /bin/readlink -f in the coreutils package.»
readlink -f (or realpath , which is an older utility kept for compatibility) will additionally expand all symbolic links, which is not necessarily desirable.
@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.
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.
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).
@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.
Instead of the pwd command, use the PWD variable (it’s in POSIX as well):
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.
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.
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")"
to answer your question with what you use right now:
the alias expands at the position where you are typing right now. you typed:
you could use a function to avoid that:
you can use that as usual:
@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).
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 *
Get absolute path of files using ‘find’ command
You can use bash ‘s Tilde Expansion to get the absolute path of the current working directory, this way find prints the absolute path for the results as well:
find ~+ -type f -name "filename"
If executed in ~/Desktop , this is expanded to
find /home/yourusername/Desktop -type f -name "filename"
/home/yourusername/Desktop/filename
If you want to use this approach with the current working directory’s parent directory you need to cd before calling find :
cd .. && find ~+ -type f -name "filename"
find "$(cd ..; pwd)" -name "filename"
Thanks, I was just testing $(cd ..; pwd) . Here it works OK, but if I do it alone in a Terminal, I can’t get the parent dir. I get «Bash:
Yes ( . ) means execute in a subshell, the output gets written to stdout. $( . ) stands for «command substitution». The latter can be used as if it were a variable expansion.
@Scrutinizer — I think you misunderstand how find works. If you use the full path in your search, you get the full path in your output. find /home/your_user -name foo . As OP is using «../» , hard to guess the full path to give in an answer.
Try using the -exec option of find :
find .. -name "filename" -exec readlink -f <> \;
Note: readlink prints the value of a symbolic link or canonical file name.
I like the simplicity of this solution but I found xargs to be much faster. find .. -name «filename» | xargs readlink -f
This worked for me, but will only return the first occurrence.
realpath $(find . -type f -name filename -print -quit)
To get full paths for all occurrences (as suggested by Sergiy Kolodyazhnyy)
find . -type f -name filename -print0 | xargs -0 realpath
Exactly what I needed (just the first occurrence and to print the full path including the filename in the output. Thank you Sir
Try with -printf . This also works with files with blank spaces.
find .. -name «filename» -printf $PWD/»%f\n»
Unless I totally misunderstand, it is as simple as this:
find $(realpath .) -name 'river.jpg'
By specifying the full real path as a start, find will implicitly output this full path as a search result.
The bash command realpath converts the current (or any other directory as ./images) into its real path). the $(realpath .) converts the output to a variable, as if it was typed manually, e.g. /home/myusername