Wenn ich in einem Bibliothekscode bin, wie erkenne ich den Pfad zur Datei des Codes, der gerade ausgeführt wird? Ich weiß, wie ich den Pfad der obersten Perl-Datei erhalte, indem ich mir ARGV
anschaue, aber wenn ich eine Bibliothek lade, wie kann diese Bibliothek wissen, an welchem Pfad sie sich befindet?
Antworten
Zu viele Anzeigen?Das __FILE__
-Token gibt Ihnen den vollständigen Pfad einschließlich des Dateinamens. Sie können File::Spec verwenden, um es in Komponenten aufzuteilen:
my ($volume, $directory, $file) = File::Spec->splitpath(__FILE__);
Der einfachste Weg, den Dateinamen der aktuellen ausführbaren Datei zu finden, ist mit FindBin:
use FindBin;
use File::Spec;
print "das Verzeichnis meines Skripts ist: " . $FindBin::Bin . "\n";
print "der Basisname meines Skripts ist: " . $FindBin::Script . "\n";
print "der kanonische Speicherort meines Skripts ist: " . File::Spec->catfile($FindBin::Bin, $FindBin::Script) . "\n";
Intern können Sie einige dieser Informationen abrufen, indem Sie auf $0
(den Namen des Skripts, wie es an der Befehlszeile aufgerufen wurde) und __FILE__
, welches der Name der derzeit ausgeführten Datei ist. (Siehe perldoc perlvar.)
Um den Dateinamen des derzeit ausgeführten Moduls zu extrahieren, beginnen Sie mit der Untersuchung von __PACKAGE__
, führen Sie etwas Substitutionsmagie durch und sehen Sie dann den Dateinamen in %INC
nach:
(my $filename = __PACKAGE__ ) =~ s#::#/#g;
$filename .= '.pm';
my $abs_filename = $INC{$filename};
Ich mache das in einer meiner Initialisierungsbibliotheken, um ein Konfigurationsskript in einem Pfad relativ zum aktuellen Modul zu finden (ich habe mehrere Code-Zweige nebeneinander installiert, jeder mit leicht unterschiedlichen Konfigurationen):
# Verwenden Sie den Speicherort des aktuellen Moduls als Anleitung, um Konfigurationen zu finden
(my $filename = __PACKAGE__ ) =~ s#::#/#g;
$filename .= '.pm';
(my $path = $INC{$filename}) =~ s#/\Q$filename\E$##g; # / und Dateiname entfernen
my $abs_config_file = File::Spec->catfile($path, $config_file);
MyApp->initialize($abs_config_file);
Jede über use
oder require
eingebundene Bibliotheken erzeugt einen Eintrag im speziellen %INC
Hash. (Siehe perlvar).
Zum Beispiel:
use strict;
use warnings;
use Data::Dumper;
print Dumper \%INC;
Dies wird eine Ausgabe ähnlich der folgenden erzeugen:
$VAR1 = {
'warnings/register.pm' => '/usr/lib/perl5/5.8.8/warnings/register.pm',
'bytes.pm' => '/usr/lib/perl5/5.8.8/bytes.pm',
'XSLoader.pm' => '/usr/lib64/perl5/5.8.8/x86_64-linux-thread-multi/XSLoader.pm',
'Carp.pm' => '/usr/lib/perl5/5.8.8/Carp.pm',
'Exporter.pm' => '/usr/lib/perl5/5.8.8/Exporter.pm',
'strict.pm' => '/usr/lib/perl5/5.8.8/strict.pm',
'warnings.pm' => '/usr/lib/perl5/5.8.8/warnings.pm',
'overload.pm' => '/usr/lib/perl5/5.8.8/overload.pm',
'Data/Dumper.pm' => '/usr/lib64/perl5/5.8.8/x86_64-linux-thread-multi/Data/Dumper.pm'
};
Zusätzlich gibt es eine universelle __FILE__
Konstante, die den aktuellen Dateinamen zurückgibt. (Siehe auch __PACKAGE__
).
Dies ist der Ausschnitt, den ich normalerweise verwende, um den Pfad für den ausführenden Code zu erhalten.
use Cwd qw/abs_path/;
my ($real_path) = abs_path($0) =~ m/(.*)myscript.pl/i;
Dies setzt den tatsächlichen Verzeichnispfad in $real_path. Normalerweise führe ich auch chdir $real_path
nach diesem Befehl aus, um sicherzustellen, dass mein Code tatsächlich aus dem richtigen Verzeichnis ausgeführt wird (normalerweise, wenn ich einen Windows-Dienst mit Win32::Daemon schreibe).
Die exportierte abs_path
Unterfunktion gibt den Pfad zur Datei (Name/Griff) zurück, den Sie als Argument verwenden. In diesem Fall habe ich $0
verwendet, was der Name des ausgeführten Perl-Skripts ist.
Ich empfehle, sich Cwd auf Cpan für etwas mehr Anleitung anzusehen.