Linux:查找给定“原始”文件的所有符号链接?(反向“readlink”)

b4qexyjb  于 2022-12-26  发布在  Linux
关注(0)|答案(7)|浏览(188)

考虑以下命令行代码段:

$ cd /tmp/
$ mkdir dirA
$ mkdir dirB
$ echo "the contents of the 'original' file" > orig.file
$ ls -la orig.file 
-rw-r--r-- 1 $USER $USER 36 2010-12-26 00:57 orig.file

# create symlinks in dirA and dirB that point to /tmp/orig.file:

$ ln -s $(pwd)/orig.file $(pwd)/dirA/
$ ln -s $(pwd)/orig.file $(pwd)/dirB/lorig.file
$ ls -la dirA/ dirB/
dirA/:
total 44
drwxr-xr-x  2 $USER $USER  4096 2010-12-26 00:57 .
drwxrwxrwt 20 root          root          36864 2010-12-26 00:57 ..
lrwxrwxrwx  1 $USER $USER    14 2010-12-26 00:57 orig.file -> /tmp/orig.file

dirB/:
total 44
drwxr-xr-x  2 $USER $USER  4096 2010-12-26 00:58 .
drwxrwxrwt 20 root          root          36864 2010-12-26 00:57 ..
lrwxrwxrwx  1 $USER $USER    14 2010-12-26 00:58 lorig.file -> /tmp/orig.file

此时,我可以使用readlink来查看符号链接的"原始"文件(我猜这里通常的术语是"目标"或"源",但在我的脑海中,它们也可能是相反的概念,所以我将称之为"原始"),即

$ readlink -f dirA/orig.file 
/tmp/orig.file
$ readlink -f dirB/lorig.file 
/tmp/orig.file

...然而,我想知道的是-有没有一个命令,我可以运行的'原始'文件,并找到所有的符号链接指向它?换句话说,类似于(伪):

$ getsymlinks /tmp/orig.file
/tmp/dirA/orig.file 
/tmp/dirB/lorig.file

提前感谢您的任何意见,
干杯!

7uzetpgm

7uzetpgm1#

使用GNU find,这将查找硬链接或符号链接到文件的文件:

find -L /dir/to/start -samefile /tmp/orig.file
bz4sfanl

bz4sfanl2#

我还没有看到这样做的命令,这不是一件容易的任务,因为目标文件不包含任何关于哪些源文件指向它的信息。
这类似于“硬”链接,但至少它们总是在同一个文件系统上,所以你可以用find -inode来列出它们。软链接的问题更大,因为它们可以跨文件系统。
我认为您需要做的基本上是对整个层次结构中的每个文件执行ls -al,并使用grep搜索-> /path/to/target/file
例如,下面是我在系统上运行的一个例子(为了可读性而进行了格式化--最后两行实际上在真实的输出的 one line上):

pax$ find / -exec ls -ald {} ';' 2>/dev/null | grep '\-> /usr/share/applications'
lrwxrwxrwx 1 pax pax 23 2010-06-12 14:56 /home/pax/applications_usr_share
                                         -> /usr/share/applications
gr8qqesn

gr8qqesn3#

灵感来自Gordon Davisson的评论。这与另一个答案类似,但我使用exec得到了想要的结果。我需要一些东西,可以找到符号链接,而不知道原始文件的位置。

find / -type l -exec ls -al {} \; | grep -i "all_or_part_of_original_name"
rfbsl7qr

rfbsl7qr4#

符号链接不跟踪指向给定目的地的内容,因此最好检查每个符号链接以查看它是否指向所需的目的地,例如

for i in *; do
    if [ -L "$i" ] && [ "$i" -ef /tmp/orig.file ]; then
        printf "Found: %s\n" "$i"
    fi
done
9ceoxa92

9ceoxa925#

这是我想到的。我在OS X上做这个,它没有readlink -f,所以我不得不用一个helper函数来代替它。如果你有一个合适的readlink -f,你可以用它来代替。而且,在这种情况下,while ... done < <(find ...)的使用不是严格需要的,一个简单的find ... | while ... done就可以了;但是如果你想在循环中设置一个变量(比如匹配文件的计数),管道版本会失败,因为while循环将在一个子shell中运行。最后,注意我使用find ... -type l,所以循环只在符号链接上执行,而不是其他类型的文件。

# Helper function 'cause my system doesn't have readlink -f
readlink-f() {
    orig_dir="$(pwd)"
    f="$1"
    while [[ -L "$f" ]]; do
        cd "$(dirname "$f")"
        f="$(readlink "$(basename "$f")")"
    done
    cd "$(dirname "$f")"
    printf "%s\n" "$(pwd)/$(basename "$f")"
    cd "$orig_dir"
}

target_file="$(readlink-f "$target_file")" # make sure target is normalized

while IFS= read -d '' linkfile; do
    if [[ "$(readlink-f "$linkfile")" == "$target_file" ]]; then 
        printf "%s\n" "$linkfile"
    fi
done < <(find "$search_dir" -type l -print0)
lyfkaqu1

lyfkaqu16#

function list_symlinks() {
    oIFS="${IFS}"; IFS=$'\n';
    declare -a results=($(
        sudo find / -type l -ls 2>&1 \
        | grep -i " ${1}" \
        | sed -e 's/\ \{2,\}/\ /g' -e "s/^\ //" 
      ));
    for x in ${results[@]}; do
      [[ $(
            echo -e "${x}" \
            | grep -v -c 'No such file or directory'
          ) -gt 0 \
      ]] && echo -e "${x}" | cut -d' ' -f11-13 ;
    done; IFS="${oIFS}";
    return 0;
  }; alias list-symlinks='list_symlinks';

$ list-symlinks /bin/nc.openbsd ;

/etc/alternatives/nc -> /bin/nc.openbsd
/etc/alternatives/netcat -> /bin/nc.openbsd
np8igboo

np8igboo7#

这对于你想做的事情来说可能太简单了,但我发现它很有用。它没有从字面上回答你的问题,因为它不是“在原始文件上运行”,但它完成了任务。但是,更多的硬盘访问。而且,它只适用于“软”链接文件,这是大多数用户链接文件。
从数据存储目录或用户数据目录的根目录(symlinked“文件”到orig.file可能驻留的位置)运行find命令:

# find -type l -ls |grep -i 'orig.file'

# find /Starting/Search\ Path/ -type l -ls |grep -i '*orig*'

我通常会使用名称的一部分,例如'*orig*'开始,因为我们知道用户会重命名(前缀)一个简单命名的文件与一个更具描述性的,如“Jan report from伦敦_ orig.file.2015.01.21“或什么。
注意:我从来没有得到-samefile选项为我工作。
干净、简单、易记
希望这能帮到什么人兰迪斯。

相关问题