如何检查路径是否位于符号链接后面

如何检查路径是否位于符号链接后面

我有一个文件列表,我需要知道其中哪些文件位于符号链接后面。例如。

var/storage/media/foo.jpg
var/storage/documents/bar.doc
var/logs/baz.log

如果只是var/storage一个符号链接,那么我想要获取列表:

var/storage/media/foo.jpg
var/storage/documents/bar.doc

原始列表中的每个文件可能存在也可能不存在
(例如,即使symlinked/documents文件夹丢失,我仍然希望bar.doc出现在结果中。

我如何在 bash 中实现这一点?
如果可能的话,一行代码是最好的。

答案1

找到一种方法将给定路径转换为其父级列表。(在 Bash 中,通过剥离最后一个组件会更容易,在其他语言中,将路径拆分为组件并在循环中重新连接它们可能会更容易 - 假设它是没有驱动器号或其他花哨语法的 Unix 样式路径)。

然后,对于结果列表中的每个项目,执行常规检查以确定它是否是符号链接(例如,在 sh/bash 中[ -h the_path ]对每个父母/祖父母/等执行此操作)。

一句话:

cat files.txt | perl -MList::Util=reductions -n -E 'chomp; say if grep {-l} reductions {"$a/$b"} split "/"'

不是一行代码(尽管你可以把所有内容都写在一行中非常如果需要的话可以排长队):

is_behind_symlink() {
    local path=$1
    while [ "$path" ]; do
        if [ -L "$path" ]; then
            return 0
        fi
        case $path in
            */*) path=${path%/*} ;;
            *) break ;;
        esac
    done
    return 1
}
while read -r path; do
    if is_behind_symlink "$path"; then
        echo "$path"
    fi
done < files.txt

您也可以这样做,但是每个文件会生成两个子进程,因此速度不快:

is_behind_symlink() {
    local path=$1
    [[ "$(realpath -s "$path")" != "$(realpath -m "$path")" ]]
}

这是每个路径一个过程(仍然不是很好)并且依赖于解析namei -l(这样做不是好风格):

is_behind_symlink() {
    local path=$1
    namei -l -n "$path" | grep -q ^l
}

答案2

此命令将从当前目录开始递归列出目标为目录的符号链接:

find . -type l -xtype d

你可以使用这个改编版本来构建你的解决方案 查找命令

相关内容