Pregunta

¿Cómo consigo que Perl lea el contenido de un directorio determinado en una matriz?

comillas invertidas Puedo hacerlo, pero ¿existe algún método que utilice 'scandir' o un término similar?

¿Fue útil?

Solución

opendir(D, "/path/to/directory") || die "Can't open directory: $!\n";
while (my $f = readdir(D)) {
    print "\$f = $f\n";
}
closedir(D);

EDITAR:Oh, lo siento, me perdí la parte "en una matriz":

my $d = shift;

opendir(D, "$d") || die "Can't open directory $d: $!\n";
my @list = readdir(D);
closedir(D);

foreach my $f (@list) {
    print "\$f = $f\n";
}

EDITAR2:La mayoría de las otras respuestas son válidas, pero quería comentar sobre esta respuesta concretamente, en el que se ofrece esta solución:

opendir(DIR, $somedir) || die "Can't open directory $somedir: $!";
@dots = grep { (!/^\./) && -f "$somedir/$_" } readdir(DIR);
closedir DIR;

Primero, documentar lo que está haciendo ya que el cartel no lo hizo:está pasando la lista devuelta de leerdir() a través de un grep() que solo devuelve aquellos valores que son archivos (a diferencia de directorios, dispositivos, canalizaciones con nombre, etc.) y que no comienzan con un punto (lo que hace que el nombre de la lista @dots engañoso, pero eso se debe al cambio que hizo al copiarlo de la documentación readdir()).Dado que limita el contenido del directorio que devuelve, no creo que sea técnicamente una respuesta correcta a esta pregunta, pero ilustra un modismo común utilizado para filtrar nombres de archivos en perla, y pensé que sería valioso documentarlo.Otro ejemplo visto mucho es:

@list = grep !/^\.\.?$/, readdir(D);

Este fragmento lee todo el contenido del identificador de directorio D excepto '.' y '..', ya que rara vez se desean usarse en el listado.

Otros consejos

Una solución rápida y sucia es utilizar globo

@files = glob ('/path/to/dir/*');

IO::Dir es agradable y también proporciona una interfaz hash vinculada.

Del perldoc:

use IO::Dir;
$d = IO::Dir->new(".");
if (defined $d) {
    while (defined($_ = $d->read)) { something($_); }
    $d->rewind;
    while (defined($_ = $d->read)) { something_else($_); }
    undef $d;
}

tie %dir, 'IO::Dir', ".";
foreach (keys %dir) {
    print $_, " " , $dir{$_}->size,"\n";
}

Entonces podrías hacer algo como:

tie %dir, 'IO::Dir', $directory_name;
my @dirs = keys %dir;

Esto lo hará, en una línea (tenga en cuenta el comodín '*' al final)

@files = </path/to/directory/*>;
# To demonstrate:
print join(", ", @files);

Podrías usar DirHandle:

use DirHandle;
$d = new DirHandle ".";
if (defined $d)
{
    while (defined($_ = $d->read)) { something($_); }
    $d->rewind;
    while (defined($_ = $d->read)) { something_else($_); }
    undef $d;
}

DirHandle proporciona una interfaz alternativa y más limpia para el opendir(), closedir(), readdir(), y rewinddir() funciones.

A continuación se muestra un ejemplo de cómo recurrir a una estructura de directorios y copiar archivos desde un script de respaldo que escribí.

sub copy_directory {
my ($source, $dest) = @_;
my $start = time;

# get the contents of the directory.
opendir(D, $source);
my @f = readdir(D);
closedir(D);

# recurse through the directory structure and copy files.
foreach my $file (@f) {
    # Setup the full path to the source and dest files.
    my $filename = $source . "\\" . $file;
    my $destfile = $dest . "\\" . $file;

    # get the file info for the 2 files.
    my $sourceInfo = stat( $filename );
    my $destInfo = stat( $destfile );

    # make sure the destinatin directory exists.
    mkdir( $dest, 0777 );

    if ($file eq '.' || $file eq '..') {
    } elsif (-d $filename) { # if it's a directory then recurse into it.
        #print "entering $filename\n";
        copy_directory($filename, $destfile); 
    } else { 
        # Only backup the file if it has been created/modified since the last backup 
        if( (not -e $destfile) || ($sourceInfo->mtime > $destInfo->mtime ) ) {
            #print $filename . " -> " . $destfile . "\n";
            copy( $filename, $destfile ) or print "Error copying $filename: $!\n";
        } 
    } 
}

print "$source copied in " . (time - $start) . " seconds.\n";       
}

Similar a lo anterior, pero creo que la mejor versión es (ligeramente modificada) de "perldoc -f readdir":

opendir(DIR, $somedir) || die "can't opendir $somedir: $!";
@dots = grep { (!/^\./) && -f "$somedir/$_" } readdir(DIR);
closedir DIR;

de: http://perlmeme.org/faqs/file_io/directory_listing.html

#!/usr/bin/perl
use strict;
use warnings;

my $directory = '/tmp';

opendir (DIR, $directory) or die $!;

while (my $file = readdir(DIR)) {
    next if ($file =~ m/^\./);
    print "$file\n";
}

El siguiente ejemplo (basado en un ejemplo de código de perldoc -f readdir) obtiene todos los archivos (no directorios) que comienzan con un punto del directorio abierto.Los nombres de los archivos se encuentran en la matriz @dots.

#!/usr/bin/perl

use strict;
use warnings;

my $dir = '/tmp';

opendir(DIR, $dir) or die $!;

my @dots 
    = grep { 
        /^\./             # Begins with a period
    && -f "$dir/$_"   # and is a file
} readdir(DIR);

# Loop through the array printing out the filenames
foreach my $file (@dots) {
    print "$file\n";
}

closedir(DIR);
exit 0;


closedir(DIR);
exit 0;
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top