在 Unix 中比较 2 个符号链接的优雅方法是什么?
假设我输入了以下命令:
ln -s /usr/share/g s1
ln -s /usr/share/g s2
ln -s ../share/g /usr/lib/s3
ln -s /usr/share/h s4
然后我想要一个命令说 s1 和 s2 相等(与 /usr/share/g 是否实际存在无关),s1 和 s4 不相等,s2 和 s4 不相等。 (就我的目的而言,报告 s3 与 s1 和 s2 不同就足够了;但是,如果可以在路径标准化后进行比较,这可能会有用。)
对于 GNU 系统(可能还有其他系统,但我不能说),有
readlink(1)
:
$ touch a
$ ln -s a b
$ readlink b
a
您可以在比较中使用它:
$ test $(readlink -f a) = $(readlink -f b)
$ echo $?
0
您可以对文件执行 stat -L 并比较设备和索引节点号。 简单的例子:
#!/bin/bash
DI_A=$(stat -c "%d.%i" -L "$1")
DI_B=$(stat -c "%d.%i" -L "$2")
if [ "$DI_A" == "$DI_B" ]; then
echo "same file"
else
echo "other file"
fi
使用
stat -L
或解析 ls -l
的输出(使用 sed 或 cut 或类似方法):
fileone=`ls -l s1 | sed 's/.*-> //'`
filetwo=`ls -l s2 | sed 's/.*-> //'`
if [ "$fileone" = "$filetwo" ]
then
echo "They're the same!"
fi
要标准化路径,请使用 realpath:
fileone=`ls -1 s1 | sed 's/.*-> //'`
fileone=`realpath $fileone`
# etc...
错误:
$ 测试 $(readlink -f a) = $(readlink -f b)
因为
a
或 b
可能指向带有空格的名称。
右:
cmp -s <(readlink -- a) <(readlink -- b)
echo $?
如果需要递归检查,请说
readlink -f
而不是 readlink
。仅当 --
或 a
是变量时才需要双破折号 b
,例如 $1
、$2
、$var
…。仅当您需要比较结果进行进一步处理而不是打印输出 -s
时,才需要开关 cmp
。
我能想到的两种方法,你可以对这两个文件使用 ls -l 。您可以在输出的“->”之后看到实际路径。例如
# ls -ltr msdfasdffff
lrwxrwxrwx 1 root root 10 Jun 30 19:05 msdfasdffff -> blah.sh
您可以使用
获取文件名# ls -l msdfasdffff | awk -F"-> " '{print $NF}'
blah.sh
然后你可以与另一个链接进行比较。
另一种方法是使用find
# var1=$(find . -name "s1" -printf "%l")
# var2=$(find . -name "s2" -printf "%l")
然后你可以使用 if/else 比较这两个变量