我正在尝试在 shell 脚本中检测文件是否是指向目录的符号链接。我正在这样做:
if [[ -L "$out_dir" && -d "$out_dir" ]]
then
echo "Dir is a symlink"
else
echo "Dir is not a symlink"
fi
但是,这个方法失败了。下面是一些实验:
bash-3.2$ ls -ail .. 共 16 8004466 drwxr-xr-x 10 用户名 1177235957 340 7月 18日 15:41 ./ 1020189 drwxr-xr-x 10 用户名 1177235957 340 7月 18日 15:16 ../ 8004467 drwxr-xr-x 12 用户名 1177235957 408 7月 18日 15:16 .git/ 8004528 -rw-r--r-- 1 用户名 1177235957 501 7月 18日 15:16 .gitignore 8004919 lrwxr-xr-x 1 用户名 1177235957 22 Jul 18 15:41 依赖项 -> ../../lmi/Dependencies
因此../Dependencies
,根据 ls,是一个符号链接,但是:
bash-3.2$ 测试 -L ../Dependencies bash-3.2$ 回显 $? 0 bash-3.2$ 测试 -h ../Dependencies bash-3.2$ 回显 $? 0
这两个不应该都返回 1 吗?我是否误解了它的工作原理?如何实现我的目标,即检测文件是否是指向目录的符号链接?
答案1
您的实验的退出值是正确的。当test
实用程序评估表达式时,如果表达式评估结果为真,test
则返回零(真)退出状态;否则返回1(假)。
因此,在您的示例中,test -L ../Dependencies
返回 0(真),因为../Dependencies
是符号链接。如果../Dependencies
不是符号链接test
将返回 1(false)。
shell 脚本if
语句是正确的,但您可以添加echo
命令来查看 shell 脚本运行时是否存在其他问题。例如,您可以在语句echo
前添加两个命令if
:
echo "path is '$PWD'"
echo "out_dir is '$out_dir'"
答案2
我会选择一个更复杂的解决方案(因为这适合我的个性,但现在这并不重要......)
for x in $(ls -lp|egrep ^[dl].*\/$); do
case $(echo $x|cut -c 1) in
"d") echo "This is a dir";;
"l") echo "This is a link";;
esac
done
简而言之,ls -lp
打印所有目录的长格式,末尾带有斜杠。长格式的第一个字符告诉我们模式(d
用于目录、l
用于链接、-
用于常规文件等)。有了这些信息,我们可以使用egrep
来过滤以ls
结尾的目录和链接列表/
,并使用来进一步过滤我们的列表。注意:由于 中的选项,case
此循环还将过滤掉链接文件-p
ls
答案3
我最终得到了以下解决方案:
function is_sym_link()
{
readlink $1 > /dev/null
return $?
}
它可能无法覆盖所有情况,但对于我的环境来说已经足够了。不幸的是,我不知道为什么原来的版本不起作用。