2011-07-05 17 views
8

me gustaría eliminar un enlace simbólico roto en un directorio usando Perl.¿Cómo puedo detectar que un enlace simbólico está roto en Perl?

En mi mente sólo tenía que mostrar el archivo de un directorio y la prueba es este un enlace simbólico (-l) y si devuelve falso simplemente lo desvincule.

pero parece que cuando se utiliza readir para listar todos los archivos de mis enlaces simbólicos rotos no se recoganized como un archivo. Como mi enlace no apunta a nada, entiendo por qué.

Entonces: ¿Cómo puedo detectar si un enlace simbólico que se rompe en Perl?

Gracias,

ACTUALIZACIÓN

Todo el archivo en $ myDir son enlaces simbólicos, ya sean válidos o rotos. Cuando visualizo @files solo obtengo una lista de enlace simbólico válido.

opendir DIR, $myDir; 
my @files = grep(/$regexp/,readdir(DIR)); 
closedir DIR; 
print "filenames : @files\n"; 
+0

¿Qué quiere decir "no están recoganized como un archivo"? por qué? muestra tu código – ysth

Respuesta

8

Hay dos principales llamadas al sistema pertinentes, stat() and lstat(). La llamada lstat() le dirá que es un enlace simbólico (pero en otros archivos, se comporta igual que stat()). Esto le permite determinar que el nombre es un enlace simbólico. La llamada al sistema stat() sigue un enlace simbólico hasta su final, y le informa sobre el archivo (o directorio) al final del enlace. Si la llamada stat() falla en el enlace simbólico, entonces el enlace simbólico se rompe o que está tratando de acceder a un directorio o un archivo en el que no tiene permiso.

Los operadores de Perl file test incluyen -l para detectar si un nombre es un enlace simbólico. Puede usar las funciones de Perl stat y lstat explícitamente. Entre estos, deberías poder determinar si un enlace simbólico está roto o no, pero probablemente deberías planear escribir una función para hacer el trabajo.

Es probable que no es necesario utilizar la función de Perl readlink. Tenga cuidado con el sistema subyacente readlink() llamada; ¡no devuelve una cadena terminada en nulo!

Es interesante que ni Perl ni su módulo POSIX admiten la función realpath(). Sin embargo, el módulo PathTools sí lo admite. Si realpath falla, en un enlace simbólico, el enlace simbólico no funciona (también conocido como roto).

+0

Todas las respuestas fueron geniales. Yo solo validé este para la explicación. Gracias. – Spredzy

4

Aquí hay un código que he usado para eliminar enlaces rotos:

chdir $dir  or die; 
opendir(DIR, '.') or die; 

foreach my $link (readdir DIR) { 
    next unless -l $link and not -e readlink($link); 

    print "Removing broken link $link\n"; 
    unlink $link; 
} 

closedir DIR; 

Tenga en cuenta que es importante que el directorio que contiene los enlaces es el directorio actual. readdir devuelve solo nombres de archivo, y los enlaces pueden ser relativos.

+1

+1: Buen punto acerca de la relatividad de los nombres. Puede agregar el valor de 'readdir' al nombre (relativo o absoluto) del directorio y trabajar desde allí:' next a menos que -l "$ dir/$ link" y no -e "$ dir/$ link" '. Omití el 'readlink' en esa reescritura; Creo que está bien, ya que el O/S lee el enlace por usted. –

+0

+1 ¡Lo mismo que @Jonathan Leffier, por la relatividad de los nombres! – Spredzy

3

Comprobar para enlaces rotos (chequeando solo el nivel superior si hay enlaces simbólicos a los enlaces simbólicos):

use strict; 
use warnings; 
use autodie; 
opendir my $dirh, '.'; 
while (my $file = readdir $dirh) { 
    if (-l $file) { 
     my $target = readlink $file; 
     if (! -e $target && ! -l $target) { 
      print "$file -> $target broken\n"; 
     } 
    } 
} 
2

Uso readlink() y stat() el resultado.

6

combinación con lstatstat:

say "dangling link at $fn" if (lstat $fn and not stat $fn); 

actualización: a mí me funciona ...

[email protected]:~/t/dl$ perl -E 'opendir $dh, "."; say $_ for grep { !stat $_ and lstat $_ } readdir $dh' 
foo 
[email protected]:~/t/dl$ ls -l 
total 0 
-rw-rw-r-- 1 salva salva 0 2011-07-05 12:34 f 
lrwxrwxrwx 1 salva salva 11 2011-07-05 12:00 fii -> /etc/shadow 
lrwxrwxrwx 1 salva salva 12 2011-07-05 11:59 foo -> /etc/hjdkshf 
1

Uso de la función integrada de pegote Perl? Para ejemplos:

@files = <*>; 
foreach $file (@files) { 
    print $file . "\n"; 
} 

Para una específica $dir:

@files = <$dir*>; 
foreach $file (@files) { 
    print $file . "\n"; 
} 
Cuestiones relacionadas