2010-09-22 27 views
12

que suelen utilizar algo así como¿Cómo puedo enumerar todos los archivos en un directorio usando Perl?

my $dir="/path/to/dir"; 
opendir(DIR, $dir) or die "can't open $dir: $!"; 
my @files = readdir DIR; 
closedir DIR; 

o, a veces utilizo glob, pero de todos modos, siempre tengo que añadir una línea o dos para filtrar . y .. que es bastante molesto. ¿Cómo sueles llevar a cabo esta tarea común?

+7

Desde la explosión de las respuestas, se puede ver que depende enteramente de lo que los resultados que desea obtener. :) – Ether

+1

entonces IEDOWRYWTG? : P –

+0

Posible duplicado de * [¿Cómo puedo leer el contenido de un directorio en Perl?] (Http://stackoverflow.com/questions/22566/how-do-i-read-in-the-contents-of -a-directory-in-perl) *. –

Respuesta

7

normalmente voy a utilizar el glob método:

for my $file (glob "$dir/*") { 
    #do stuff with $file 
} 

Esto funciona bien a menos que el directorio tiene muchos archivos. En esos casos hay que volver a readdir en un bucle while (poniendo readdir en el contexto de lista es tan malo como el glob):

open my $dh, $dir 
    or die "could not open $dir: $!"; 

while (my $file = readdir $dh) { 
    next if $file =~ /^[.]/; 
    #do stuff with $file 
} 

menudo, sin embargo, si estoy leyendo un montón de archivos en un directorio , Quiero leerlos de manera recursiva. En esos casos yo uso File::Find:

use File::Find; 

find sub { 
    return if /^[.]/; 
    #do stuff with $_ or $File::Find::name 
}, $dir; 
+0

El uso de '[.] 'es muy curioso --- ¿por qué prefieres eso a' \ .'? –

+1

@Chris Jester-Young Simplemente me gusta más. Parece menos ruidoso (ver [síndrome de palillo de diente inclinado] (http://en.wikipedia.org/wiki/Leaning_toothpick_syndrome)). Además, y esto es racionalizar, los escapes en expresiones regulares tienden a significar que "el siguiente personaje hace algo especial" (por ejemplo, '\ x {2e}'), pero '\ .' significa que es solo un punto. Dado que la mayoría de los personajes no tienen un significado especial dentro de las clases de caracteres, es un buen mecanismo de escape. –

13
my @files = grep {!/^\./} readdir DIR; 

Esto excluirá todos los dotfiles así, pero eso es por lo general lo que usted quiere.

7

Si algunos de los dotfiles son importantes,

my @files = grep !/^\.\.?$/, readdir DIR; 

sólo se excluye . y ..

+4

Bueno, podría excluir ".. \ n", lo cual es legal en Unix. No es que desee ese nombre de archivo para nadie, pero la gente hace cosas extrañas para ver si alguien ignora un archivo que se han colado en su directorio. Puede solucionarlo con a \ z en lugar de $ :) –

2

Cuando sólo quiero los archivos (en oposición a los directorios), utilizo grep con una prueba -f:

my @files = grep { -f } readdir $dir; 
+4

Esto solo funcionará si el identificador de directorio es para el directorio actual. –

+0

@Chris: buen punto, uno tendría que hacer un chdir primero, o construir un nombre de ruta absoluto en el grep con 'File :: Spec-> catfile ($ dirname, $ _)'. – Ether

8

A menudo uso File::Slurp. Los beneficios incluyen: (1) Muere automáticamente si el directorio no existe. (2) Excluye . y .. de forma predeterminada. Su comportamiento es como readdir en el sentido de que no devuelve las rutas completas.

use File::Slurp qw(read_dir); 

my $dir = '/path/to/dir'; 
my @contents = read_dir($dir); 

Otro módulo útil es File::Util, que proporciona muchas opciones al leer un directorio. Por ejemplo:

use File::Util; 
my $dir = '/path/to/dir'; 
my $fu = File::Util->new; 
my @contents = $fu->list_dir($dir, '--with-paths', '--no-fsdots'); 
+1

... que no era un requisito del PO. Solo quería filtrar '.' y' ..'. – CanSpice

+0

Agradable. ¿Puedo hacer que devuelva las rutas completas (no los basenames)? –

+1

'my @contents = map {" $ dir/$ _ "} read_dir ($ dir);' – toolic

0

Gracias Chris and Ether por sus recomendaciones. Usé lo siguiente para leer una lista de todos los archivos (directorios excluidos), desde un manejador de directorio que hace referencia a un directorio que no es mi directorio actual, en una matriz. La matriz siempre faltaba un archivo cuando no se utiliza la ruta absoluta en la declaración grep

use File::Slurp; 

print "\nWhich folder do you want to replace text? " ; 
chomp (my $input = <>); 
if ($input eq "") { 
print "\nNo folder entered exiting program!!!\n"; 
exit 0; 
} 

opendir(my $dh, $input) or die "\nUnable to access directory $input!!!\n"; 

my @dir = grep { -f "$input\\$_" } readdir $dh; 
Cuestiones relacionadas