[Dresden-pm] Nachfrage wegen rätselhaften Verhalten von Perl

Hans-Dietrich Kirmse hd.kirmse at gmx.de
Son Jan 1 13:33:26 PST 2006


Hallo,

herzlichen Dank für die schnelle Antwort.

Allerdings bin ich halt nur autodidaktischer Laienkünstler mit
Hobbyambitionen, fehlenden Englischkenntnissen mit Blick auf den
wohlverdienten(?) Ruhestand, dazu nur Lehrer (kein Programmierer),
der wegen Zeitmangels nur gelegentlich mal paar Zeilen in Perl
zusammenschreibt. In der Schule sind andere Programmiersprachen
gefordert.

will damit sagen, dass ich mehrere Stunden gebraucht habe, diese
Mail (vermutlich nur ansatzweise) zu verstehen. Inzwischen habe ich
(mit meinen wenigen Englischkenntnissen) mich doch einigermaßen schlau
gemacht, was der Unterschied ist zwischen unbenannten und benannten
Referenzen auf Prozeduren und wie man sie erzeugt und aufruft und
dann habe ich auch diese Lösung (so einigermaßen) verstanden.

Habe also sehr viel gelernt - Danke.

A. Pagaltzis schrieb:

>># kopiert den Inhalt eines Verzeichnisses in ein anderes
>>sub copydir
>>{
>>  my $quelle = shift;
>>  my $ziel   = shift;
>>
>>  my $recht  = 0777;
>>
>>  find (\&kopieren,$quelle);
>>
>>  # ist sonst die Routine "wanted", was aber nichts zur Sache tut
>>  sub kopieren
> 
> 
> Das funktioniert nie. Du hast hier eine benannte Closure; eine
> solche wird an die lexikalischen Variablen des ersten Aufrufs
> gebunden.
> 
> Du müsstest hier eigentlich Warnungen der Form
> 
>     Variable "$quelle" will not stay shared at $script line $x.
>     Variable "$ziel" will not stay shared at $script line $y.
> 
> erhalten haben.

Es war Teil eines CGI-Scripts und das sollte ausgebaut werden.
Apache hat mir keine Fehlermeldungen gebracht. jetzt (auf der
Konsole erhalte ich diese auch.


> Das behebst du einfach, indem du stattdessen eine anonyme
> Funktion verwendest.

so einfach ist das nun doch nicht ;)  - siehe [*]

>>    my $reststring;  # der Pfad zur Datei gekürzt um den Pfad zur Quelle
>>
>>    # wenn es nicht das Ausgangsverzeichnis (die Quelle) ist
>>    if ($quelle ne $File::Find::name) {
>>      # dann holen wir uns den "Rest" des Dateinamens nach der Quelle
>>      if ($File::Find::name =~ /^$quelle(.*)$/) { $reststring = $1 };
> 
> 
> Das ist umständlich und fehlerträchtig. Stattdessen solltest
> einfach find() mit der Option no_chdir aufrufen und dann $_
> verwenden.

schon das war für mich eine Nuss zu knacken, wie ich "find" mit
dieser Option aufrufe. Aber den Unterschied zum einfachen Aufruf
habe ich noch nicht erkannt. Wenn ich die Doku (CPAN) richtig
verstanden habe, da steht dort sogar, dass $_ gleich $File::Find::Name
ist.

Wegen dem fehlerträchtig: es mag alles sein, aber für mich sind
die Module auf dem CPAN eher neu und die Doku eher nicht zugängig.
Dagegen sind reg. Ausdrücke für mich eine Wohltat und da es hier sehr
einfache Lösungen gibt, wird wohl für diesen Fall diese Lösung für
mich deutlich weniger fehlerträchtig sein. Da ich ja auch Nachfragen
bzw. Support auf Dauer tätigen muss, ist mir das eigene Verständnis
sehr wichtig.

>>      # wenn das gefundene Element ein Verzeichnis ist
>>      if (-d $File::Find::name) {
>>        # dann legen wir im Ziel ein neues Verzeichnis an
>>        mkdir($ziel.$reststring,$recht);
>>      } else {
>>        # dann kopieren wir diese Datei in dieses Ziel
>>        copy($File::Find::name,$ziel.$reststring);
> 
> 
> Bitte immer File::Spec verwenden, um Pfade zusammenzubasteln.

habe ich mir angeschaut. Das liefert ja wirklich viel. Aber
auch das war/ist für mich absolutes Neuland und in keinem der Bücher
das ich besitze wurde darauf hingewiesen. Ich besitze m.E. fast
alle deutschsprachigen Bücher. Das ist das erste Mal überhaupt,
dass mir diese Empfehlung unter die Augen kam.

>>die Variable "$recht" soll in den Konfigurationsteil, […] gibt
>>man die dann als Sting an oder wie macht man das korrekt?
> 
> 
> Du willst ziemlich sicherlich die Rechte aus dem Quellbaum auf
> den Zielbaum übertragen, 

mit Sicherheit nicht. ich wollte die definitiv *setzen*. es sollte
u.U. sogar erweitert werden, weil auch noch ACLs mit drin hängen
und die sollen bei weitem nicht gleich sein (verschiedene Lehrer
sollen für verschiedene Klausurnutzer Zugriffsrechte bekommen)

> nicht einen konstanten Wert verwenden;
> und schon garnicht 777, es sei denn, die Sicherheit des Servers
> ist dir piepe. :-)

Welchen Wert, das sollten die (Dresdner) Serverentwickler festlegen.
ich wollte das so vergeben, dass das Script auch unter Linux sofort
läuft. also deshalb 0777. für mich bleibt weiter die Frage, wie
gibt man diese z.B. im Konfigurationsteil an. (habe ich nicht aus
dem Beispiel herausholen können und ich vermute, meine Schreibweise
ist falsch.)

> Summa summarum:

   :

>         find( {
                 ^
      das ist doch dann auch eine Referenz, oder irre ich mich?

>             no_chdir => 1,
>             wanted   => sub {
               ^^^^^^^^^^^^^^^^^
   ich denke, das war der Knackpunkt [*] - Danke.

> In diesem Code fehlt allerdings ebenso wie auch in deinem
> ursprünglichen jegliche Fehlerbehandlung.

ich hatte ja alles rausgeschmissen, was meiner Meinung nach nicht
zum Problem beigetragen hatte.

Fazit: ich habe lange gebraucht, diese Mail vollständig zu erfassen.
Habe auch etliche Details noch nicht erfasst, aber das eigentliche
Problem im Griff. Ich bedanke mich nochmals für diese Hilfestellung.


mit freundlichen Grüßen (aus Thüringen)
Hans-Dietrich