2009-10-02 16 views
9

Estoy usando este código para obtener una lista de todos los archivos en un directorio específico:¿Cómo puedo obtener una lista de todos los archivos con una cierta extensión desde un directorio específico?

opendir DIR, $dir or die "cannot open dir $dir: $!"; 
my @files= readdir DIR; 
closedir DIR; 

¿Cómo puedo modificar el código o añadir algo a ella de modo que sólo busca los archivos de texto y sólo cargas la matriz con el prefijo del nombre de archivo?

contenidos de directorios de ejemplo: contenido de la matriz

. 
.. 
923847.txt 
98398523.txt 
198.txt 
deisi.jpg 
oisoifs.gif 
lksdjl.exe 

Ejemplo:

files[0]=923847 
files[1]=98398523 
files[2]=198 
+0

Considere también el uso de una variable léxica para el manejador de su directorio: 'opendir my $ dirh, $ dir_path o die" no puede abrir dir $ dir: $! ";' –

Respuesta

10
my @files = glob "$dir/*.txt"; 
for (0..$#files){ 
    $files[$_] =~ s/\.txt$//; 
} 
+0

¿Alguna idea de cómo eliminar el directorio también? Mi salida es/dir/dir/dir/923847 ... ¿cómo puedo obtener el 923847? – CheeseConQueso

+0

glob agrega trabajo adicional aquí. Consulte http://stackoverflow.com/questions/1506801/what-reasons-are-there-to-prefer-glob-over-readdir-or-vice-versa-in-perl –

5

que es suficiente para cambiar una línea:

my @files= map{s/\.[^.]+$//;$_}grep {/\.txt$/} readdir DIR; 
2

para conseguir el". txt "archivos, puede usar un archivo de prueba oper ator (-f: archivo regular) y una expresión regular.

my @files = grep { -f && /\.txt$/ } readdir $dir; 

De lo contrario, se puede buscar archivos de texto sólo, usando (operador de la prueba archivo de texto ASCII) -T de Perl

my @files = grep { -T } readdir $dir; 
+0

-T para probar si tiene un "archivo de texto" – reinierpost

+0

Buen punto; de la página perldoc en el operador (http://perldoc.perl.org/5.8.8/perlfunc.html), "-T \t El archivo es un archivo de texto ASCII (suposición heurística)." si está buscando archivos ".txt", esto hará exactamente lo que pregunte sin adivinar. –

3

Si puede utilizar las nuevas características de Perl 5.10, esta es la forma Yo lo escribiría

use strict; 
use warnings; 
use 5.10.1; 
use autodie; # don't need to check the output of opendir now 

my $dir = "."; 

{ 
    opendir my($dirhandle), $dir; 
    for(readdir $dirhandle){ # sets $_ 
    when(-d $_){ next } # skip directories 
    when(/^[.]/){ next } # skip dot-files 

    when(/(.+)[.]txt$/){ say "text file: ", $1 } 
    default{ 
     say "other file: ", $_; 
    } 
    } 
    # $dirhandle is automatically closed here 
} 

O si tiene directorios muy grandes, se puede utilizar un bucle while.

{ 
    opendir my($dirhandle), $dir; 
    while(my $elem = readdir $dirhandle){ 
    given($elem){ # sets $_ 
     when(-d $_){ next } # skip directories 
     when(/^[.]/){ next } # skip dot-files 

     when(/(.+)[.]txt$/){ say "text file: ", $1 } 
     default{ 
     say "other file: ", $_; 
     } 
    } 
    } 
} 
1

Sólo tiene que utilizar esto:

my @files = map {-f && s{\.txt\z}{} ? $_ :()} readdir DIR; 
1

Ésta es la forma más sencilla que he encontrado (como en el ser humano legible) utilizando la función glob:

# Store only TXT-files in the @files array using glob 
my @files = grep (-f ,<*.txt>); 
# Write them out 
foreach $file (@files) { 
    print "$file\n"; 
} 

Además, el "-f "asegura que solo los archivos reales (y no los directorios) se almacenen en la matriz.

+0

¿Por qué retroceder la edición? 'foreach $ file' no es estrictamente seguro. Si prefieres 'foreach' a' for', ¿por qué no 'foreach my $ file'? –

+0

¿Por qué editar a alguien más cosas viejas cuando no sabes la razón de por qué se publicó en primer lugar? Demonios, ni siquiera sé la razón por la que escribí esta pieza de código hace más de tres años, pero dado que tengo el hábito de probar algo, probablemente funcionó bien, y es probable que haya una razón por la que no agregué el estricto declaración tampoco. Sin embargo, ¿significa eso que debería aceptar una edición aleatoria, e incluso quiero pasar el tiempo probándola? Diablos, no!Es por eso que me pareció mucho más seguro simplemente retroceder. – Kebman

+0

Para que quede claro, no fui yo quien lo editó, solo vi la edición y pensé que mejoró la respuesta. Es extraño que uses un 'lexical' @ files y luego un '$ file global. –

Cuestiones relacionadas