Comment lire le contenu d'un répertoire en Perl?
-
09-06-2019 - |
Question
Comment puis-je obtenir Perl pour lire le contenu d'un répertoire donné dans un tableau?
Backticks peut le faire, mais est-il une méthode à l'aide de 'scandir" ou un terme similaire?
La solution
opendir(D, "/path/to/directory") || die "Can't open directory: $!\n";
while (my $f = readdir(D)) {
print "\$f = $f\n";
}
closedir(D);
EDIT:Oh, désolé, a raté le "dans un tableau" de la partie:
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";
}
EDIT2:La plupart des autres réponses sont valables, mais je voulais commenter cette réponse plus précisément, dans laquelle cette solution est proposée:
opendir(DIR, $somedir) || die "Can't open directory $somedir: $!";
@dots = grep { (!/^\./) && -f "$somedir/$_" } readdir(DIR);
closedir DIR;
Tout d'abord, afin de documenter ce qu'il fait depuis l'affiche n'a pas:c'est en passant de la liste retournée à partir de readdir() par le biais d'un grep() qui ne retourne que les valeurs qui sont des fichiers (par opposition à des répertoires, des appareils, tubes nommés, etc.) et qui ne commencent pas par un point (ce qui rend le nom de la liste @dots
trompeur, mais c'est en raison du changement, il a fait lors de la copie de la readdir() documentation).Car elle limite le contenu du répertoire, il retourne, je ne pense pas que c'est techniquement une réponse correcte à cette question, mais il illustre un idiome commun utilisé pour filtrer les noms de fichiers dans Perl, et j'ai pensé qu'il serait utile de document.Un autre exemple vu beaucoup est:
@list = grep !/^\.\.?$/, readdir(D);
Ce lit tout le contenu du répertoire poignée D sauf '.' et '..', car ceux-ci sont très rarement souhaité être utilisé dans la liste.
Autres conseils
Un moyen rapide et sale solution est d'utiliser glob
@files = glob ('/path/to/dir/*');
IO::Dir est agréable et offre une égalité de hachage interface.
À partir de la 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";
}
Donc, vous pourriez faire quelque chose comme:
tie %dir, 'IO::Dir', $directory_name;
my @dirs = keys %dir;
Cela fera, en une seule ligne (notez le '*' joker à la fin)
@files = </path/to/directory/*>;
# To demonstrate:
print join(", ", @files);
Vous pouvez utiliser 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
fournit une alternative plus propre interface à l' opendir()
, closedir()
, readdir()
, et rewinddir()
fonctions.
Voici un exemple de recursing à travers une structure de répertoire et de la copie de fichiers d'une sauvegarde script que j'ai écrit.
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";
}
Comme ci-dessus, mais je pense que la meilleure version est (légèrement modifiée) 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";
}
L'exemple suivant (basé sur un exemple de code à partir de perldoc -f readdir) obtient tous les fichiers (pas les répertoires) en commençant par une période de l'open directory.Les noms de fichiers sont trouvés dans le tableau @points.
#!/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;