如何检查是否/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_dev
stat -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 -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 $?
.
这适用于绑定安装,但可能不适用于网络安装。