如何在 Bash 中检查两条路径是否相等?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33980224/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 13:58:05  来源:igfitidea点击:

How to check if two paths are equal in Bash?

linuxbashshellunixsh

提问by James Ko

What's the best way to check if two paths are equal in Bash? For example, given the directory structure

在 Bash 中检查两条路径是否相等的最佳方法是什么?例如,给定目录结构

~/
  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?

有没有本地 Bash 方法来做到这一点?

回答by geirha

Bash's test commands have a -efoperator for this purpose

Bash 的测试命令有一个-ef用于此目的的操作符

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.

回答by zedfoxus

You can use realpath. For example:

您可以使用realpath. 例如:

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

也看看这里的类似答案:bash/fish command to print absolute path to a file

回答by Tom Zych

Native bash way:

原生 bash 方式:

pwd -Preturns the physical directory irrespective of symlinks.

pwd -P无论符号链接如何,都返回物理目录。

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,它将遵循符号链接,但将您留在物理目录中:

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

回答by rob mayoff

If you have coreutils 8.15 or later installed, you have a realpathcommand that fully normalizes a path. It removes any .and ..components, makes the path absolute, and resolves all symlinks. Thus:

如果您安装了 coreutils 8.15 或更高版本,则您有一个realpath完全规范化路径的命令。它删除任何...组件,使路径成为绝对路径,并解析所有符号链接。因此:

if [ "$(realpath "$path1")" = "$(realpath "$path2")" ]; then
   echo "Same!"
fi

回答by Peter Cordes

Methods based on resolving symlinks fail when there are other factors involved. For example, bind mounts. (Like mount --bind /raid0/var-cache /var/cache

当涉及其他因素时,基于解析符号链接的方法会失败。例如,绑定安装。(喜欢mount --bind /raid0/var-cache /var/cache

Using find -samefileis a good bet. That will compare filesystem and inode number.

使用find -samefile是一个不错的选择。这将比较文件系统和 inode 编号。

-samefileis 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.)

-samefile是 GNU 扩展。即使在 Linux 上,busybox find 也可能没有它。GNU 用户空间和 Linux 内核经常一起使用,但你可以没有另一个,这个问题只标记了 Linux 和 bash。)

# params: two paths.  returns true if they both refer to the same file
samepath() {
    # test if find prints anything
    [[ -s "$(find -L "" -samefile "")" ]]  # 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 -Lfor cases where you want to follow symlinks in the final path component:

您可以find -L在希望遵循最终路径组件中的符号链接的情况下使用:

$ 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.

显然,这适用于引用目录或任何类型文件的路径,而不仅仅是常规文件。它们都有 inode 编号。



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 -Ldereferences symlinks for -samefile, as well as for the list of paths. So either or both can be symlinks.

所以find -L取消引用符号链接-samefile,以及路径列表。所以其中一个或两个都可以是符号链接。