Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
What's the best way to check if two paths are equal in Bash? For example, given the directory structure
Desktop/
Downloads/ (symlink to ~/Downloads)
Downloads/
photo.png
and assuming that the current directory is the home directory, all of the following would be equivalent:
./ and ~
~/Desktop and /home/you/Desktop
./Downloads and ~/Desktop/Downloads
./Downloads/photo.png and ~/Downloads/photo.png
Is there a native Bash way to do this?
–
–
–
–
–
Another way is to use cd -P
, which will follow symlinks but leave you in the physical directory:
cd -P "$dir1"
real1=$(pwd)
cd -P "$dir2"
real2=$(pwd)
# compare real1 with real2
–
–
–
If you have coreutils 8.15 or later installed, you have a realpath
command that fully normalizes a path. It removes any .
and ..
components, makes the path absolute, and resolves all symlinks. Thus:
if [ "$(realpath "$path1")" = "$(realpath "$path2")" ]; then
echo "Same!"
Methods based on resolving symlinks fail when there are other factors involved. For example, bind mounts. (Like mount --bind /raid0/var-cache /var/cache
Using find -samefile
is a good bet. That will compare filesystem and inode number.
-samefile
is a GNU extension. Even on Linux, busybox find probably won't have it. GNU userspace and Linux kernel often go together, but you can have either without the other, and this question is only tagged Linux and bash.)
# params: two paths. returns true if they both refer to the same file
samepath() {
# test if find prints anything
[[ -s "$(find -L "$1" -samefile "$2")" ]] # as the last command inside the {}, its exit status is the function return value
e.g. on my system:
$ find /var/tmp/EXP/cache/apt/archives/bash_4.3-14ubuntu1_amd64.deb -samefile /var/cache/apt/archives/bash_4.3-14ubuntu1_amd64.deb
/var/tmp/EXP/cache/apt/archives/bash_4.3-14ubuntu1_amd64.deb
$ stat {/var/tmp/EXP,/var}/cache/apt/archives/bash_4.3-14ubuntu1_amd64.deb
File: ‘/var/tmp/EXP/cache/apt/archives/bash_4.3-14ubuntu1_amd64.deb’
Device: 97ch/2428d Inode: 2147747863 Links: 1
File: ‘/var/cache/apt/archives/bash_4.3-14ubuntu1_amd64.deb’
Device: 97ch/2428d Inode: 2147747863 Links: 1
You can use find -L
for cases where you want to follow symlinks in the final path component:
$ ln -s /var/cache/apt/archives/bash_4.3-14ubuntu1_amd64.deb foo
$ find /var/cache/apt/archives/bash_4.3-14ubuntu1_amd64.deb -samefile foo
$ find -L /var/cache/apt/archives/bash_4.3-14ubuntu1_amd64.deb -samefile foo
/var/cache/apt/archives/bash_4.3-14ubuntu1_amd64.deb
Obviously this works for paths which refer to directories or any type of file, not just regular files. They all have inode numbers.
usage:
$ samepath /var/cache/apt/ /var/tmp/EXP/cache/apt/ && echo true
$ ln -sf /var/cache/apt foobar
$ samepath foobar /var/tmp/EXP/cache/apt/ && echo true
samepath /var/tmp/EXP/cache/apt/ foobar && echo true
samepath foobar && echo true # doesn't return true when find has an error, since the find output is empty.
find: `': No such file or directory
So find -L
dereferences symlinks for -samefile
, as well as for the list of paths. So either or both can be symlinks.
–
–
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.