英文:
Why does the Linux shell command test -ef not work on soft links as its manual describes?
问题
I create a hard
link to student.sh
and a soft
link to student.sh
.
The hard
links have different inodes than soft
links.
But when comparing the soft
with student.sh
by using the test -ef
command, it does not work as expected.
I had checked the manuals of the ln
and test
commands but still confused with them.
$ 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
test
# ❌ inode is different
$ [ ./student.sh -ef ./soft ] && echo yes || echo no
yes
$ [ ./student.sh -ef ./hard ] && echo yes || echo no
yes
> update test case
./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
wanted
# 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
英文:
I create a hard
link to student.sh
and a soft
link to student.sh
.
The hard
links have different inodes than soft
links.
But when comparing the soft
with student.sh
by using the test -ef
command, it does not work as expected.
I had checked the manuals of the ln
and test
commands but still confused with them.
$ 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
test
# ❌ inode is different
$ [ ./student.sh -ef ./soft ] && echo yes || echo no
yes
$ [ ./student.sh -ef ./hard ] && echo yes || echo no
yes
> update test case
./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
wanted
# 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
答案1
得分: 1
Barmar在评论中提到,并且在关于条件表达式的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
这应该适用于任何POSIX兼容的Shell,不仅仅是bash
,只要GNU coreutils的stat(1)
命令可用,考虑到您正在谈论Linux,这似乎是一个安全的选择。如果使用其他环境,可能需要进行调整;例如,NetBSD的stat(1)
使用-f
而不是-c
。
英文:
Like Barmar mentioned in a comment, and as documented in the bash
manual section on conditional expressions:
>Unless otherwise specified, primaries that operate on files follow symbolic links and operate on the target of the link, rather than the link itself.
You can use stat(1)
to get the device number and inode without following symbolic links, and compare those values, though:
$ 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
This should work on any POSIXish shell, not just bash
, as long as the GNU coreutils stat(1)
command is available, which seems a safe bet since you're talking about Linux. Might need to be adjusted if using some other enviroment; the NetBSD stat(1)
, for example, uses -f
instead of -c
).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论