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)
向您显示设备编号以及您的目录的安装位置。
以下命令为包含文件的挂载点提供唯一名称$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
实用程序,但其语法各不相同:
stat
报告该st_dev
字段为stat -c %D -- "$file"
.stat
与 GNU coreutils 兼容的a 。其他人stat
则%c
别无选择;您可以使用,stat -t -- "$file" | awk '{print $8}'
但这仅适用于文件名不包含空格的情况,或者stat -t -- "$file" | awk 'END {print $(NF-8)}'
处理任意文件名但不处理将来在stat
输出中添加字段的情况。stat
实用程序,它需要stat -f %d -- "$file"
.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)
POSIX 中可用的最佳万无一失的解决方案是比较stat(2) 函数提供的文件设备 ID。
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 $?
.
这适用于绑定安装,但可能不适用于网络安装。