代码之家  ›  专栏  ›  技术社区  ›  Paul

如何在Perl哈希中表示文件系统的符号链接?

  •  8
  • Paul  · 技术社区  · 14 年前

    服务器故障时, How to list symbolic link chains? (不是我的问题)讨论列出所有符号链接并跟踪它们。为了实现这一点,我们首先考虑一个目录。

    我想写一个简短的实用程序来完成这个任务。将符号链接中的对放进哈希,然后处理哈希看起来很容易。

    但我可能会有这样的东西:

    ls -l
    total 0
    lrwxrwxrwx 1 pjb pjb 1 2010-02-23 08:48 a -> b
    lrwxrwxrwx 1 pjb pjb 1 2010-02-23 08:48 b -> c
    lrwxrwxrwx 1 pjb pjb 1 2010-02-23 09:03 c -> a
    lrwxrwxrwx 1 pjb pjb 1 2010-02-23 09:17 trap -> b
    lrwxrwxrwx 1 pjb pjb 1 2010-02-23 09:17 x -> y
    lrwxrwxrwx 1 pjb pjb 1 2010-02-23 09:17 y -> b
    

    很明显, a->b->c 是一个循环,这个陷阱指向一个循环,但要知道 x 指向一个循环,我需要遵循一点。

    一个哈希表示是:

    a => b
    b => c
    c => a
    trap => b
    x => y
    y => b
    

    但是,一旦我知道了循环是什么,反向表示对于将循环标记到错误的起点更好。

    下面是一些问题:

    • 哈希是表示符号链接的最佳结构吗?
    • 将文件系统的图形用循环类型的片段分开,最好的方法是什么?
    • 有没有比从所有起点手动搜索所有循环更好的算法?
    • 从图论的角度来看——这是不是 CPAN 已经好了?如果没有,哪些是好的助手模块?
    3 回复  |  直到 14 年前
        1
  •  7
  •   Brad Gilbert    14 年前

    有一个 Graph CPAN上的模块,您可以使用它,如下所示:

    #! /usr/bin/perl
    
    use warnings;
    use strict;
    
    use Graph;
    
    my $g = Graph->new;
    my $dir = @ARGV ? shift : ".";
    
    opendir my $dh, $dir or die "$0: opendir $dir: $!";
    while (defined(my $name = readdir $dh)) {
      my $path = $dir . "/" . $name;
    
      if (-l $path) {
        my $dest = readlink $path;
        die "$0: readlink $path: $!" unless defined $dest;
    
        $g->add_edge($name => $dest);
      }
      else {
        $g->add_vertex($name);
      }
    }
    
    my @cycle = $g->find_a_cycle;
    if (@cycle) {
      $" = ' -> '; #" # highlighting error
      print "$0: $dir: at least one cycle: @cycle\n";
    }
    else {
      print "$0: $dir: no cycles\n";
    }
    

    例如,在与问题目录结构类似的目录中,输出是

    $ ../has-cycle 
    ../has-cycle: .: at least one cycle: c -> a -> b
        2
  •  2
  •   Brad Gilbert    14 年前

    看一下CPAN模块 File::Spec::Link .resolve方法表示它反复遍历一个链接以查找链接的目标。

    模块的解析方法如下:

    解析(链接)
    通过重复调用linked返回最终由$link链接到的非链接。如果无法解析链接,则返回UNdef

    我用这个模块找到了一个符号链接的目标,它的目标依次是符号链接等等。但我不确定这是否检测到循环符号链接。

        3
  •  -1
  •   TMN    14 年前

    您需要存储的不仅仅是链接的名称。要么抓取inode编号(如果您的fs支持它),要么抓取其他一些独特的方面。如果一个不存在,那么考虑创建您自己的,可能通过校验名/创建/上次修改日期。无论哪种方式,您都需要某种方法来唯一地标识每个链接。我见过一些实用程序简单地限制了链接的数量(在8到255之间),并声明任何超过此限制的内容都是循环,但我总是认为这是“廉价的出路”。:)