如何检查是否/my/dir
与属于同一分区/
?
这是为了集成到脚本中。绑定安装架应正确处理。欢迎使用POSIX兼容解决方案。
如何检查是否/my/dir
与属于同一分区/
?
这是为了集成到脚本中。绑定安装架应正确处理。欢迎使用POSIX兼容解决方案。
Answers:
您可以使用stat检查此内容:
$ stat -c '%d %m' /proc/sys/
3 /proc
显示设备号和目录的安装位置。
stat
shell命令不是POSIX ...
以下命令为包含该文件的安装点提供了唯一的名称$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
实用程序,但是其语法有所不同:
stat
报告该st_dev
字段stat -c %D -- "$file"
。stat
与GNU coreutils兼容的。其他人则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"
并进行比较:
perl -e 'exit((stat($ARGV[0]))[0] != (stat($ARGV[1]))[0])' -- "$file1" "$file2"
请注意,在某些极端情况下,所需的结果尚不清楚。例如,使用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"
df
并不总是提供设备名称,但有时会对其进行符号链接,例如/dev/disk/by-uuid/ca09b761-ae1b-450f-8a46-583327b48fb4
使其df
不可靠。到目前为止,唯一可靠的选择是使用stat
基于-解决方案。
df
设备报告的名称是什么,两次调用之间的名称都是一致的,因此可以进行比较。
df
报告/dev/sda6
和/dev/disk/by-uuid/ca09b...
均指同一设备,但挂载点不同。尝试从每个安装点尝试文件时,字符串比较测试显然失败。
mount /dev/sda6 /mnt1
其次mount /dev/sda6 /mnt2
是魅力。cat /proc/mounts
很好。但是,仅由于Wheezy /dev/disk/by-uuid/ca09b...
被显示df
为根文件系统的设备。进一步尝试使用此simlink或UUID=ca09b...
mount语法来装载它,除了/dev/sda6
在df
(in 不知道如何重现它在引导过程中所做的事情之外,其他什么都不会结束)之外,其他事情都没有结束。
POSIX中最好的万无一失的解决方案是比较stat(2)函数提供的文件的设备ID。
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 $?
。
这在绑定安装上很好用,但可能不适用于网络安装。