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

发布于 2024-08-23 01:30:33 字数 1086 浏览 6 评论 0原文

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

我想编写一个简短的实用程序来执行此操作。将符号链接中的对放入哈希中然后处理哈希看起来很容易。

但随后我可能会遇到类似的情况:

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 code> 指向一个循环,我需要稍微跟踪一下。

一种哈希表示是:

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

但是,一旦我知道循环是什么,反向表示更适合将循环标记为错误的起点。

所以这里有一些问题:

  • 哈希是表示符号链接的最佳结构吗?
  • 分离文件系统图以将循环组件从树组件区分为具有循环类型片段的树枝的最佳方法是什么?
  • 有没有比从所有起点手动搜索所有循环更好的算法?
  • 从图论的角度来看——CPAN 中已经有这种东西了吗?如果没有,有哪些好的辅助模块?

On Server Fault, How to list symbolic link chains? (not my question) talks about listing all the symbolic links and following them. To make this doable, let's consider a single directory at first.

I want to write a short utility that does this. It looks easy to put pairs from symbolic links into a hash and then process the hash.

But then I might have something like:

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

where it is obvious that a->b->c is a loop, and that trap points into a loop, but to know x points into a loop I need to follow a bit.

One hash representation is:

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

But the reverse representation is better for marking loops to bad starting points, once I know what the loops are.

So here's some questions:

  • Is a hash the best structure to represent symbolic links?
  • what's the best way to separate the graph of the file system to tell the loopy components from the tree components to the twig with a loop type pieces?
  • Is there a better algorithm than manually searching for all the loops from all the starting points?
  • From a graph-theory perspective -- is this sort of thing in the CPAN already? If not, what are some good helper modules?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

停顿的约定 2024-08-30 01:30:33

CPAN 上有一个 Graph 模块,您可以按如下方式使用:

#! /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

There's a Graph module on CPAN that you might use as in the following:

#! /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";
}

For example, in a directory similar in structure to the one in your question, the output is

$ ../has-cycle 
../has-cycle: .: at least one cycle: c -> a -> b
孤独陪着我 2024-08-30 01:30:33

查看 CPAN 模块 File::Spec::Link。解析方法表示它会重复遍历链接以找到链接的目标。

该模块的resolve方法有这样的说法:

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

我曾使用此模块来查找符号链接的目标,其目标又是符号链接等。但我不确定这是否检测到循环符号链接。

Have a look at the CPAN module File::Spec::Link. The resolve method says that it traverses a link repeatedly to find the linked target.

The resolve method of the module has this to say:

resolve($link)
  Returns the non-link ultimately linked to by $link, by repeatedly calling linked. Returns undef if the link can not be resolved

I had used this module to find a target of symbolic link whose target was in turn a symlink and so on. But I am not sure if this detects the cyclic symbolic links.

昵称有卵用 2024-08-30 01:30:33

您需要存储的不仅仅是链接名称。获取 inode 编号(如果您的 FS 支持)或其他一些独特的方面。如果不存在,请考虑创建自己的,也许可以通过对名称/创建/上次修改日期进行校验和来创建。无论哪种方式,您都需要某种方法来唯一标识每个链接。我见过一些实用程序只是对链接数量设置限制(8 到 255 之间),并将任何超过此限制的内容声明为循环,但我始终认为这是“采取廉价的出路”。 :)

You need to store more than just the name of the link. Either grab the inode number (if your FS supports that) or some other unique aspect. If one doesn't exist, then consider creating your own, maybe by checksumming the name/create/last-modified date. Either way, you need some way to uniquely identify each link. I've seen some utilities that simply put a limit on the number of links (between 8 and 255) and declare anything that exceeds this limit a loop, but I always considered that as "taking the cheap way out". :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文