检查 2 个目录是否托管在 Linux 上的同一分区上

检查 2 个目录是否托管在 Linux 上的同一分区上

如何检查是否/my/dir与 位于同一分区/

这是为了集成到脚本中。应正确处理绑定安装。欢迎 POSIX 兼容解决方案。

答案1

您可以使用 stat 来检查:

$ stat -c '%d %m' /proc/sys/
3 /proc

显示设备编号以及目录的安装位置。

答案2

以下命令为包含该文件的安装点提供唯一的名称$file

df -P -- "$file" | awk 'NR==2 {print $1}'

这适用于任何POSIX系统。该-P选项强加了可预测的格式;第二行的第一个字段是“文件系统名称”。因此,要检查两个文件是否位于同一安装点下:

if [ "$(df -P -- "$file1" | awk 'NR==2 {print $1}')" = \
     "$(df -P -- "$file2" | awk 'NR==2 {print $1}')" ]; then
  echo "$file1 and $file2 are on the same filesystem" ; fi

或者,保存几个流程调用:

if df -P -- "$file1" "$file2" |
   awk 'NR!=1 {dev[NR] = $1} END {exit(dev[2] != dev[3])}'; then
  echo "$file1 and $file2 are on the same filesystem" ; fi

一些操作系统的卷名称中可以有空格。在这种情况下,没有完全可靠的方法来解析输出df

在幕后,您可以通过st_dev返回的字段来识别包含文件的文件系统stat。没有可移植的方法可以通过 shell 脚本执行此操作。有些系统有一个stat实用程序,但其语法有所不同:

  • 在非嵌入式 Linux、Cygwin 或其他具有 GNU coreutils 的系统上,在调用时stat报告该字段。st_devstat -c %D -- "$file"
  • 一些 BusyBox 安装包括stat它与 GNU coreutils 兼容。其他人则stat没有%c选择;您可以使用stat -t -- "$file" | awk '{print $8}',但仅当文件名不包含空格,或者stat -t -- "$file" | awk 'END {print $(NF-8)}'处理任意文件名但不适用于将来向stat输出添加字段时才有效。
  • BSD系统有不同的stat公用事业这需要stat -f %d -- "$file".
  • Solaris、AIX 和其他操作系统没有stat实用程序。

如果 Perl 可用,您可以使用

perl -e 'print ((stat($ARGV[0]))[0])' -- "$file"

并进行比较:

perl -e 'exit((stat($ARGV[0]))[0] != (stat($ARGV[1]))[0])' -- "$file1" "$file2"

请注意,在某些特殊情况下,所需的结果并不明确。例如,对于 Linux 的绑定挂载, after mount --bind /foo /bar/foo/bar被认为是相同的文件系统。这两个文件实际上可能位于同一设备上,但您永远不会知道:例如,如果文件位于两个不同的网络挂载上,则客户端无法知道服务器是否正在导出不同的文件系统。

如果文件是目录并且您可以写入它们,另一种方法是创建临时文件并尝试建立硬链接。该报告报告了 Linux 绑定挂载的负面结果。

tmp1=$(TMPDIR=$dir1 mktemp)
tmp2=$(TMPDIR=$dir2 mktemp)
if ln -f -- "$tmp1" "$tmp2"; then
  echo "$dir1 and $dir2 are on the same filesystem, which supports hard links"
fi
rm -f "$tmp1" "$tmp2"

答案3

test $(df -P $path1 $path2 | awk '{if (NR!=1) {print $6}}' | uniq | wc -l) -eq 1

适用于任意数量的路径。

答案4

POSIX 中可用的最佳万无一失的解决方案是比较文件的设备 ID由提供stat(2) 函数

Perl也有类似的统计函数作为吉尔斯 指出:

perl -e 'exit((stat($ARGV[0]))[0] != (stat($ARGV[1]))[0])' -- file1 file2

但“POSIX 方式”是使用 C 程序,例如:

./checksamedev file1 file2

其源代码如下:

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

int main(int argc, char* argv[]) {
    struct stat s1, s2;
    if( argc==3 && lstat(argv[1], &s1)==0 && lstat(argv[2], &s2)==0 )
        return !(s1.st_dev == s2.st_dev);
    return 2;
}

如果两个文件的设备 ID 相等,则它们托管在同一文件系统上,在这种情况下,上面的命令返回 0(否则返回另一个值)。检查与echo $?.

这适用于绑定安装,但可能不适用于网络安装。

相关内容