2008-10-15 5 views
27

Ich möchte ls in einem Perl-Programm als Teil eines CGI-Skripts ausführen. Dazu habe ich exec(ls) verwendet, aber dies kommt nicht vom exec Anruf zurück.Wie bekomme ich eine Verzeichnisliste in Perl?

Gibt es eine bessere Möglichkeit, eine Auflistung eines Verzeichnisses in Perl zu erhalten?

Antwort

61

Exec kehrt überhaupt nicht zurück. Wenn Sie das wollten, benutzen Sie das System.

Wenn Sie nur ein Verzeichnis lesen möchten, ist open/read/close-dir möglicherweise besser geeignet.

opendir my($dh), $dirname or die "Couldn't open dir '$dirname': $!"; 
my @files = readdir $dh; 
closedir $dh; 
#print files... 
+2

Überprüfen Sie den Rückgabewert der Systembefehle: opendir ... oder sterben "... $!" Oder "Autodie verwenden"; um sie standardmäßig fatal zu machen. Ich weiß, es ist nur ein Nitpick, aber wenn Sie Anfänger beraten, ist es eine wichtige Lektion für sie. – tsee

+0

Ja, du hast Recht, ich werde es hinzufügen. Vielen Dank. –

+0

Falls sich jemand fragt, warum readdir und closedir nicht aktiviert sind: beide haben nur einen möglichen Fehler: 'invalid directory handle'. Da ich es selbst geöffnet und überprüft habe, kann ich davon ausgehen, dass es gültig ist. Auch im Listenkontext kann readddir nicht überprüft werden. –

6

Um die Ausgabe eines Systembefehls zu erhalten, müssen Sie Backticks verwenden.

$listing = `ls`; 

Perl ist jedoch gut im Umgang mit Verzeichnissen für sich. Ich würde empfehlen, File :: Find :: Rule zu verwenden.

0

Ich würde Ihnen empfehlen, einen Blick auf IPC::Open3 haben. Es erlaubt viel mehr Kontrolle über den erzeugten Prozess als das System oder die Backticks.

12

Alle anderen scheint auf der Exec-Teil der Frage stecken.

Wenn Sie eine Verzeichnisliste benötigen, verwenden Sie die in Perl integrierte glob oder opendir. Sie benötigen keinen separaten Prozess.

+0

Insbesondere tut Glob genau das, was Sie wollen: Gibt ein Array der Namen von Dateien in einem Ordner zurück. –

0

Unter Linux, ziehe ich es finden:

my @files = map { chomp; $_ } `find`; 
+0

Dies ist besonders nützlich, wenn Sie nicht nur das Verzeichnis auflisten, sondern Dateien mit bestimmten Kriterien finden möchten. Wie gesagt, du willst Dateien, die in den letzten 2 Tagen geändert wurden: my @recentFiles = map {chomp; $ _} 'finde $ theDir -maxdepth 1 -type f -mtime -2'; –

5

Noch ein anderes Beispiel:

chdir $dir or die "Cannot chroot to $dir: $!\n"; 
my @files = glob("*.txt"); 
5

EDIT: Whoops! Ich dachte, Sie wollten nur eine Liste der Verzeichnisse ... entfernen Sie den 'Verzeichnis' Anruf, um dieses Skript zu machen, was Sie wollen ...

Spielen mit Dateihandles ist meiner Meinung nach der falsche Weg. Im Folgenden finden Sie ein Beispiel für die Verwendung von File :: Find :: Rule, um alle Verzeichnisse in einem angegebenen Verzeichnis zu finden. Es scheint, als ob Sie für das, was Sie tun, über töten, aber später auf der ganzen Linie kann es sich lohnen.

Zuerst meine eine Zeile Lösung:

File::Find::Rule->maxdepth(1)->directory->in($base_dir); 

Jetzt eine herausgezogen Version mit Kommentaren. Wenn Sie File :: Find :: Rule installiert haben, sollten Sie dies problemlos ausführen können. Fürchte die CPAN nicht.

#!/usr/bin/perl 

use strict; 
use warnings; 

# See http://search.cpan.org/~rclamp/File-Find-Rule-0.32/README 
use File::Find::Rule; 

# If a base directory was not past to the script, assume current working director 
my $base_dir = shift // '.'; 
my $find_rule = File::Find::Rule->new; 

# Do not descend past the first level 
$find_rule->maxdepth(1); 

# Only return directories 
$find_rule->directory; 

# Apply the rule and retrieve the subdirectories 
my @sub_dirs = $find_rule->in($base_dir); 

# Print out the name of each directory on its own line 
print join("\n", @sub_dirs); 
+1

+1 als Datei :: Finden :: Regel ist rockt –

6

Verwenden Perl Globbing:

my $dir = </dir/path/*>