我创建了一个指向
hard
的 student.sh
链接和一个指向 soft
的 student.sh
链接。
hard
链接与 soft
链接具有不同的 inode。
但是,当使用 soft
命令将 student.sh
与 test -ef
进行比较时,它无法按预期工作。
我已经检查了 ln
和 test
命令的手册,但仍然对它们感到困惑。
$ man test
$ man ln
FILE1 -ef FILE2
FILE1 and FILE2 have the same device and inode numbers
$ ln /home/pi/Desktop/links/student.sh hard
$ ln -s /home/pi/Desktop/links/student.sh soft
$ ls -ial
278224 drwxr-xr-x 2 pi pi 4096 6月 5 23:31 .
262125 drwxr-xr-x 12 pi pi 4096 6月 5 23:17 ..
278227 -rwxr-xr-x 2 pi pi 43 6月 5 23:20 hard
278225 lrwxrwxrwx 1 pi pi 33 6月 5 23:31 soft -> /home/pi/Desktop/links/student.sh
278227 -rwxr-xr-x 2 pi pi 43 6月 5 23:20 student.sh
# ❌ inode is different
$ [ ./student.sh -ef ./soft ] && echo yes || echo no
yes
$ [ ./student.sh -ef ./hard ] && echo yes || echo no
yes
更新测试用例
./test.sh
#!/usr/bin/env bash
if [[ ./student.sh -ef ./soft ]]; then
echo "yes"
else
echo "no"
fi
if [[ ./student.sh -ef ./hard ]]; then
echo "yes"
else
echo "no"
fi
$ ./test.sh
yes
yes
# inode is different, so it should output no ✅
$ [ ./student.sh -ef ./soft ] && echo yes || echo no
no
$ [ ./student.sh -ef ./hard ] && echo yes || echo no
yes
bash
关于条件表达式的手册部分中所述:
除非另有说明,否则对文件进行操作的主程序遵循符号链接并对链接的目标进行操作,而不是对链接本身进行操作。
stat(1)
来获取设备编号和 inode 而不用跟随符号链接,并比较这些值:
$ is_same_file () { test "$(stat -c "%d %i" "$1")" = "$(stat -c "%d %i" "$2")"; }
$ if is_same_file student.sh hard; then echo yes; else echo no; fi
yes
$ if is_same_file student.sh soft; then echo yes; else echo no; fi
no
PS:
is_same_file ()
等价于以下代码
# use the keyword `function`
function is_same_file () {
# The return value is the exit status code
# of the execution result of the last line of command.
return test "$(stat -c "%d %i" "$1")" = "$(stat -c "%d %i" "$2")";
}
只要 GNU coreutils
bash
命令可用,这应该适用于任何 POSIXish shell,而不仅仅是 stat(1)
,这似乎是一个安全的选择,因为你正在谈论 Linux。如果使用其他环境可能需要调整;例如,NetBSD stat(1)
使用 -f
而不是 -c
)。