2010-02-23 18 views
8

On Server Fault, How to list symbolic link chains? (non la mia domanda) parla dell'elenco di tutti i collegamenti simbolici e del loro seguito. Per rendere questo fattibile, consideriamo inizialmente una singola directory.Come posso rappresentare i collegamenti simbolici di un file system in un hash Perl?

Voglio scrivere una breve utilità che faccia questo. Sembra facile mettere le coppie da collegamenti simbolici in un hash e quindi elaborare l'hash.

Ma allora potrei avere qualcosa di simile:

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 

dove è ovvio che a->b->c è un loop, e che i punti di trappola in un ciclo, ma per sapere x punti in un ciclo Ho bisogno di seguire una po.

Una rappresentazione hash è:

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

Ma la rappresentazione inversa è meglio per la marcatura loop a cattivi punti di partenza, una volta che so che cosa i loop sono.

Quindi, ecco alcune domande:

  • è un hash la struttura migliore per rappresentare i link simbolici?
  • qual è il modo migliore per separare il grafico del file system per indicare i componenti loopy dai componenti dell'albero al ramoscello con pezzi di tipo loop?
  • Esiste un algoritmo migliore rispetto alla ricerca manuale di tutti i loop da tutti i punti di partenza?
  • Dal punto di vista della teoria dei grafi - questo tipo di cose è già presente nello CPAN? In caso contrario, quali sono alcuni buoni moduli di supporto?
+0

La richiesta di codice di esempio per risolvere il problema è ovviamente anche incoraggiata. – Paul

+0

Mostraci ciò che hai provato fino ad ora è anche incoraggiato. :) –

+0

@brian Doh! L'ho visto principalmente come un problema ben preciso di qualcun altro, e non ho cercato di risolverlo oltre a riconoscere alcune delle insidie. – Paul

risposta

7

C'è un modulo Graph su CPAN che si potrebbe utilizzare come nel seguente:

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

Per esempio, in una directory simile nella struttura a quella nella sua interrogazione, l'uscita è

$ ../has-cycle 
../has-cycle: .: at least one cycle: c -> a -> b
+0

Grazie per aver postato questo. Intendo esaminare Graph per altri bisogni che ho, e per rispolverare questo tipo di cose. – Paul

+0

@Paul Prego! Sono felice che tu l'abbia trovato utile. –

2

Dai un'occhiata al modulo CPAN File::Spec::Link. Il metodo di risoluzione dice che attraversa ripetutamente un collegamento per trovare il bersaglio collegato.

Il metodo determinazione del modulo ha questo da dire:

determinazione ($ link)
    Restituisce il non-link in ultima analisi legata a da $ link, da chiamando ripetutamente collegato. Restituisce undef se il collegamento non può essere risolto

Avevo usato questo modulo per trovare un obiettivo di collegamento simbolico il cui obiettivo era a sua volta un collegamento simbolico e così via. Ma non sono sicuro se questo rileva i collegamenti simbolici ciclici.

-1

È necessario memorizzare più del semplice nome del collegamento. O prendi il numero di inode (se il tuo FS lo supporta) o qualche altro aspetto unico.Se non ne esiste uno, prendi in considerazione la possibilità di crearne uno, magari con il checksum del nome/creazione/data dell'ultima modifica. In entrambi i casi, è necessario un modo per identificare in modo univoco ciascun link. Ho visto alcune utilità che limitano semplicemente il numero di link (tra 8 e 255) e dichiarano tutto ciò che supera questo limite un ciclo, ma l'ho sempre considerato come "prendere l'uscita economica". :)

Problemi correlati