How to check if two paths are equal in Bash?

前端 未结 5 624
渐次进展
渐次进展 2021-01-03 20:54

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         


        
相关标签:
5条回答
  • 2021-01-03 21:29

    Native bash way:

    pwd -P returns the physical directory irrespective of symlinks.

    cd "$dir1"
    real1=$(pwd -P)
    cd "$dir2"
    real2=$(pwd -P)
    # compare real1 with real2
    

    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
    
    0 讨论(0)
  • 2021-01-03 21:29

    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
    true
    $ ln -sf /var/cache/apt foobar
    $ samepath foobar /var/tmp/EXP/cache/apt/  && echo true
    true
    samepath /var/tmp/EXP/cache/apt/ foobar   && echo true
    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.

    0 讨论(0)
  • 2021-01-03 21:30

    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!"
    fi
    
    0 讨论(0)
  • 2021-01-03 21:36

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

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

    etc...

    $ help test | grep -e -ef
          FILE1 -ef FILE2  True if file1 is a hard link to file2.
    
    0 讨论(0)
  • 2021-01-03 21:40

    You can use realpath. For example:

    realpath ~/file.txt
    Result: /home/testing/file.txt
    
    realpath ./file.txt
    Result: /home/testing/file.txt
    

    Also take a look at a similar answer here: bash/fish command to print absolute path to a file

    0 讨论(0)
提交回复
热议问题