【问题标题】:Linux: Find all symlinks of a given 'original' file? (reverse 'readlink')Linux:查找给定“原始”文件的所有符号链接? (反向“阅读链接”)
【发布时间】:2011-05-30 18:07:17
【问题描述】:

考虑以下命令行sn-p:

$ 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

提前感谢任何cmets,

干杯!

【问题讨论】:

    标签: linux bash symlink reverse


    【解决方案1】:

    受到戈登戴维森评论的启发。这类似于另一个答案,但我使用 exec 得到了想要的结果。我需要一些可以在不知道原始文件位置的情况下找到符号链接的东西。

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

    【讨论】:

      【解决方案2】:

      这对于您想要做的事情来说可能过于简单,但我觉得它很有用。 它并没有从字面上回答你的问题,因为它不是“在原始文件上运行”,但它完成了任务。但是,更多的硬盘访问。而且,它仅适用于大多数用户链接文件的“软”链接文件。

      从您的数据存储目录或用户数据目录的根目录,无论symlinked 'files' 到orig.file 可能驻留的位置,运行查找命令:

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

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

      我通常会使用名称的一部分,例如'*orig*',因为我们知道用户会用更具描述性的文件重命名(前缀)一个简单命名的文件,例如“来自伦敦的 Jan 报告_orig.file.2015.01。 21" 什么的。

      注意:我从来没有让 -samefile 选项为我工作。

      干净、简单、易记

      希望这对某人有所帮助。 兰迪斯。

      【讨论】:

        【解决方案3】:

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

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

        【讨论】:

        • 嗨@Dennis Williamson,谢谢你,+1 的回答! :) 顺便说一句,这与上面的“...目标文件包含关于哪些源文件指向它的零信息...”有什么关系; “...基本上对每个文件执行ls -al...”??这个命令是否基本相同(但可能以更优化的方式) - 或根本不同?再次感谢,干杯!
        • @sdaau:目标文件不包含信息。这个命令基本上是对链接回它的文件的蛮力搜索。
        • busybox find 有什么等效的方法吗?
        • @g.rocket:查找硬链接文件:find /dir/to/start -follow -inum $(stat -c %i /tmp/orig.file)。你也许能想出一些东西来找到符号链接,但我很快就没有想到。
        • @qodeninja:如果-samefile 的参数名称是一个目录,那么结果将是目录(或目录的符号链接)。如果要显式,在命令中指定起始目录的位置后面加上-type d,例如:find -L /dir/to/start type -d -samefile /tmp/orig.dir
        【解决方案4】:

        这就是我想出的。我在没有readlink -f 的 OS X 上执行此操作,因此我不得不使用辅助函数来替换它。如果你有一个合适的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)
        

        【讨论】:

        • 嗨@Gordon Davisson - 感谢您的代码;它对 Mac 用户也很有用!干杯!
        【解决方案5】:

        我还没有看到这个命令,这不是一件容易的事,因为目标文件包含关于源文件指向它的零信息。

        这类似于“硬”链接,但至少它们始终位于同一文件系统上,因此您可以通过find -inode 列出它们。软链接问题更大,因为它们可以跨文件系统。

        我认为您要做的基本上是对整个层次结构中的每个文件执行ls -al,然后使用grep 搜索-&gt; /path/to/target/file

        例如,这是我在我的系统上运行的一个(格式化以提高可读性 - 最后两行实际上在实际输出中的 one 行):

        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
        

        【讨论】:

        • 嗨@paxdiablo - 同样感谢您的明确回答; +接受对“硬链接”和“find -inode”的引用。干杯!
        • 别忘了你可以在安装了 nfs 的 fs 的服务器上拥有符号链接。因此,仅仅查看本地服务器可能还不够。
        • 这不适用于递归链接(链接到...的链接)或相对链接(无论 -> ../../usr/share/applications)。处理这些案件更加困难。此外,它会为每个检查的文件生成一个 ls 的新实例,这意味着它会非常慢。
        • @paxdiablo 为了速度,使用find / -type l -ls 怎么样?这会跳过非符号链接,并避免创建所有每个文件的进程(这使得它比我的答案更快)。附:我如此担心速度的原因是我的启动卷上有 824,220 个文件,如果您为每个文件创建一个进程......这将需要一段时间。
        • 我听说处理 'ls' 命令的输出是七大罪之一。
        【解决方案6】:

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-03-31
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-05-24
          • 1970-01-01
          • 2012-12-14
          • 2010-11-11
          相关资源
          最近更新 更多