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

Tot*_*tor 9 mount shell-script

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

这是用于脚本中的集成。应该正确处理绑定安装。欢迎使用 POSIX 兼容解决方案。

小智 6

您可以使用 stat 进行检查:

$ stat -c '%d %m' /proc/sys/
3 /proc
Run Code Online (Sandbox Code Playgroud)

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


Gil*_*il' 6

以下命令为包含文件的挂载点提供唯一名称$file

df -P -- "$file" | awk 'NR==2 {print $1}'
Run Code Online (Sandbox Code Playgroud)

这适用于任何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
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

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

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

  • 在非嵌入式 Linux、Cygwin 或其他带有 GNU coreutils 的系统上,在调用时stat报告该st_dev字段为stat -c %D -- "$file".
  • 一些 BusyBox 安装包括stat与 GNU coreutils 兼容的a 。其他人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"
Run Code Online (Sandbox Code Playgroud)

并进行比较:

perl -e 'exit((stat($ARGV[0]))[0] != (stat($ARGV[1]))[0])' -- "$file1" "$file2"
Run Code Online (Sandbox Code Playgroud)

请注意,在某些极端情况下,所需的结果并不明确。例如,使用Linux的绑定安装,后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"
Run Code Online (Sandbox Code Playgroud)


Tot*_*tor 1

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

Perl 有一个与Gilles指出的类似的stat 函数

perl -e 'exit((stat($ARGV[0]))[0] != (stat($ARGV[1]))[0])' -- file1 file2
Run Code Online (Sandbox Code Playgroud)

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

./checksamedev file1 file2
Run Code Online (Sandbox Code Playgroud)

其源代码如下:

perl -e 'exit((stat($ARGV[0]))[0] != (stat($ARGV[1]))[0])' -- file1 file2
Run Code Online (Sandbox Code Playgroud)

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

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