Zum Inhalt springen
View in the app

A better way to browse. Learn more.

Fachinformatiker.de

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

[Perl] rekursiv durch Dateibaum

Empfohlene Antworten

Veröffentlicht

Hallo zusammen,

ich mache gerade meine ersten Schritte mit Perl und möchte ein kleines Skript, mit dem ich rekursiv durch einen Dateibaum gehe und dort gefundene Ordner und Dateien ausgebe.

Das mache ich mit folgendem Skript

#!/usr/local/bin/perl
#
# recursively walk through a filetree
#
list_files("/home/goetzp");

sub list_files
{
opendir(DIR, @_[0]);
while($file = readdir(DIR))
{
if($file ne "." && $file ne "..")
{
$file = @_[0] . "/" . $file;

# file is a directory
if(-d $file)
{
print $file . "\n";

list_files($file);
}
else
{
print $file . "\n";
}
}
}
closedir(DIR);
}
[/PHP]

Leider läuft das Skript nur bis zum ersten Verzeichnis. Kann mir einer von Euch den Fehler nennen, ich denke, es müsste ein Anfängerfehler sein.

Ich habe versucht, die Variablen mit my oder local zu initialisieren. Das hat zwar einen Effekt, aber nicht den gewünschten. Kann aber auch sein, dass ich das Prinzip noch nicht umrissen habe.

Vielen Dank für Eure Hilfe!

Peter

Dein @_[0] was wohl der erste Wert eines Arrays sein soll, den du

deiner Sub übergibst (und den ich eher $_[0] benennen würde,

wenn ich das so richtig interpretiere)


opendir(DIR, @_[0]); 

ist imho in der while-Schleife

while($file = readdir(DIR))

    {

        if($file ne "." && $file ne "..")

        {

            $file = @_[0] . "/" . $file;


            # file is a directory

            if(-d $file)

            {

                print $file . "\n";


                list_files($file);

            }

            else

            {

                print $file . "\n";

            }

        }

    } 

nicht mehr gültig, da in der while-Schleife @_, $_ und andere Systemvariablen

jeweils neu gesetzt werden, sie gelten also immer nur im Bereich des jeweiligen

Blocks.

Grüße

Guten Morgen mtn,

vielen Dank für die Antwort! Das @ habe ich deshalb genommen, weil es in dem Tutorial, das ich verwende, heisst, dass das @ für Arrayvariablen steht und das @_ für das Array der übergebenen Parameter steht. Aber ich werde das heute abend mal ausprobieren.

Vielen Dank schon mal!

[Edit]

So, ich habe es jetzt mal schnell hier auf dem Arbeitsrechner ausprobiert. Das Zuweisen des ersten Parameters an eine Variable hat nichts gebracht.

Ich habe aber jetzt gesehen, dass das Skript scheinbar abbricht, wenn es aus der ersten Rekursion wieder zurückkommt.

Also folgender Dateibaum:

/home/pgoetz

/home/pgoetz/.file1

/home/pgoetz/.file2

/home/pgoetz/dir1/

/home/pgoetz/dir1/file1

/home/pgoetz/dir1/file2

/home/pgoetz/dir2/file1

/home/pgoetz/dir2/file2

Er gibt richtigerweise die files file1 und file2 in pgoetz aus und geht in der Rekursion in dir1. Dort gibt er auch file1 und file2 korrekt aus. Danach sollte er ja eigentlich zurück zu pgoetz gehen und dort mit dir2 fortfahren. Das passiert aber nicht.

Hat jemand einen Tipp für mich, wieso die Rekursion beim zurückkommen nicht korrekt fortfährt?

[/Edit]

Peter

Hallo zusammen,

#!/usr/local/bin/perl
#
# recursively walk through a filetree
#
list_files("/home/goetzp");

sub list_files
{
opendir(DIR, @_[0]);
while($file = readdir(DIR))
{
if($file ne "." && $file ne "..")
{
$file = @_[0] . "/" . $file;

# file is a directory
if(-d $file)
{
print $file . "\n";

list_files($file);
}
else
{
print $file . "\n";
}
}
}
closedir(DIR);
}
[/PHP]

Das is n einfacher Fehler!

ok, also du hast als startordner /home/goetzp

dann ließt du alle "Dinger" da drin aus und gibst die aus mit @_[0]."/".$file

z.b. /home/goetzp/index.html

ist $file aber ein Ordner so rufst du die Funktion mit $file auf, also mit www

jetzt will er den Ordner /www öffnen, den gibts aber nicht, aber es gibt /home/goetzp/www.

Du siehst den Fehler? ;)

Servus SNOWMAN,

ich weise doch der Variable $file den Wert des Directories plus den Filenamen zu, oder?

Die Anweisung $file = @_[0] . "/" . $file; sollte das tun und ich denke, das klappt auch, weil die erste Rekursionsstufe funktioniert. Nur beim zurückkommen aus der sub wird der nächste Ordner nicht gefunden. Kann es sein, dass das Filehandle DIR nicht mehr gültig ist, wenn die Funktion zurückkehrt? Und wenn, wie bekomme ich die gültig?

Peter

Uwaaa *anshirnklatsch* ich sollte so früh nich denken... ok, sorry, hast recht, der pfad stimmt natürlich.

aber du hast auch damit recht das DIR nicht mehr gilt.

immerhin

- Du machst DIR auf

- Du ließt alles ein

- Findest ien Ordner

- Machst DIR mit dem neuen Ordner auf

- Ließt den ein

- Machst DIR zu

- Gehst zurück und versuchst DIR zu lesen

du solltest dir vielleicht ne Variable $rootdir machen in der immer das übergeordnete Verzeichnis steht und das dann nach dem aufruf setzen

bin mir nich ganz sicher damit, aber vllt. gehts so:


sub list_files
{
opendir(DIR, @_[0]);
while($file = readdir(DIR))
{
if($file ne "." && $file ne "..")
{
$rootdir = @_[0];
$file = @_[0] . "/" . $file;

# file is a directory
if(-d $file)
{
print $file . "\n";

list_files($file);
opendir(DIR, $rootdir);
}
else
{
print $file . "\n";
}
}
}
closedir(DIR);
}
[/php]

Servus zusammen,

ich habe jetzt SNOWMANs letzten Tipp noch nicht umgesetzt, da ich im Web eine einfach zu benutzende Möglichkeit gefunden habe:

use File::Find;

find(\&<funktionsname>, <startverzeichnis>);


sub funktionsname

{

    # hier passiert was mit jeder Datei, z.B. 

    print File::Find::name

}

Ich werde aber demnächst mal die andere Lösung noch umsetzen (zumindest versuche ich es, da mich das schon noch interessiert.

Danke an alle!

Peter

Archiv

Dieses Thema wurde archiviert und kann nicht mehr beantwortet werden.

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.