Search code examples
linuxbashshellunixsh

How to check if two paths are equal in Bash?


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?


Solution

  • Bash's test commands have a -ef operator for this purpose:

    if [[ ./ -ef ~ ]]; then ...
    
    if [[ ~/Desktop -ef /home/you/Desktop ]]; then ...
    

    Here is the documentation for this operator:

    $ help test | grep -e -ef
          FILE1 -ef FILE2  True if file1 is a hard link to file2.
    $ help '[['
    [[ ... ]]: [[ expression ]]
        Execute conditional command.
    
        Returns a status of 0 or 1 depending on the evaluation of the conditional
        expression EXPRESSION.  Expressions are composed of the same primaries used
        by the `test' builtin, and may be combined using the following operators:
    
          ( EXPRESSION )    Returns the value of EXPRESSION
          ! EXPRESSION              True if EXPRESSION is false; else false
          EXPR1 && EXPR2    True if both EXPR1 and EXPR2 are true; else false
          EXPR1 || EXPR2    True if either EXPR1 or EXPR2 is true; else false
    
    [...snip...]
    

    Note that both paths of the operator have to refer to an existing file or directory for this to work. If the file or directory does not exist, the test will return false.

    If you prefer, you can use the test or [ builtins instead of double brackets:

    if test ./ -ef ~; then ...
    
    if [ ./ -ef ~ ]; then ...
    

    but [[ ... ]] is preferred for consistency, since it encompasses the complete functionality of test and [ in addition to other features, such as pattern matching and regex matching.