如何在unix(Linux)中比较2个符号链接?

问题描述 投票:0回答:5

在 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 不同就足够了;但是,如果可以在路径标准化后进行比较,这可能会有用。)

linux bash unix
5个回答
12
投票

对于 GNU 系统(可能还有其他系统,但我不能说),有

readlink(1)
:

$ touch a
$ ln -s a b
$ readlink b
a

您可以在比较中使用它:

$ test $(readlink -f a) = $(readlink -f b)
$ echo $?
0

4
投票

您可以对文件执行 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

0
投票

使用

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...

0
投票

错误:

$ 测试 $(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


-1
投票

我能想到的两种方法,你可以对这两个文件使用 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 比较这两个变量

© www.soinside.com 2019 - 2024. All rights reserved.