2016-12-23 2 views
7

Viele meiner Kollegen verwenden die folgenden Befehle in ihrem BEGIN-Block.In ein Verzeichnis wechseln und dann getcwd()

$scriptDir = dirname($0); 
chdir($scriptDir); 
$scriptDir = getcwd(); 

ich um ausgesehen haben und kann nicht umhin zu denken, dass die dritte Zeile heißt $scriptDir = getcwd(); redundant ist. Weil wir schon das Scriptdir von $scriptDir = dirname($0); haben. Am fehlt mir hier etwas?

+0

Wie unten gezeigt, verwenden Sie FindBin qw ($ RealBin); 'und ändern Sie das Verzeichnis nicht. Dateien, die in '@ ARGV' aufgelistet sind, sind relativ zu' pwd', nicht '$ RealBin'. – shawnhcorey

Antwort

7

Die dirname($0) nicht den vollständigen Pfad zurückkehren, wie Chankey Pathak und Matthias demonstrieren.

Ich möchte hinzufügen, dass es andere Möglichkeiten gibt. Zum Beispiel können Sie FindBin (auch Kern)

use FindBin qw($RealBin); 

BEGIN: { 
    my ($scriptDir) = $RealBin; 
    chdir $scriptDir    or die "Can't change to $scriptDir: $!"; 
}; 

Die $RealBin gibt das gleiche wie verwenden, was Sie zeigen, mit der Ausnahme, dass es der vollständige Pfad mit Links aufgelöst.

Die chdir kann fehlschlagen, dank ikegami für den Kommentar. In diesem Fall wird false zurückgegeben und der obige Code stirbt, passen Sie ihn entsprechend an. Beachten Sie, dass die Frage der dritten Zeile nichts damit zu tun hat.

Dieses Modul wird auch allgemein für relativen Pfad zu Bibliotheken mit lib Pragma verwendet, zum Beispiel

use lib "$RealBin/../lib"; 

was für eine noch einfachere Entscheidung trifft, vielleicht ist es für beide zu verwenden.


Noch mehr, angesichts der Beschreibung von dirnameFile::Basename (emphasis nicht Mine)

Diese Funktion ist für die Kompatibilität mit dem Befehl Unix Schale versehen ist dirname(1) und hat einen Teil seiner Macken geerbt.Trotz seines Namens gibt es NOT immer den Verzeichnisnamen, wie Sie vielleicht erwarten. Wenn Sie den Verzeichnisnamen eines Pfades verwenden möchten, verwenden Sie fileparse().

Ich würde lieber gehen sogar mit

use Cwd qw(abs_path); 

BEGIN: { 
    my ($scriptDir) = abs_path(__FILE__) =~ m|(.*)/|; 
    chdir $scriptDir    
     or die "Can't change to $scriptDir: $!"; 
}; 

wo abs_path seit __FILE__ für sich allein verwendet wird, um den vollständigen Pfad nicht zur Verfügung stellen kann. Der Regex gräbt gierig alles bis zum letzten /, also den vollständigen Pfad zum Verzeichnis des Skripts.

4
  • getcwd - Liefert die aktuelle Arbeitsverzeichnis
  • chdir - Ändert das Arbeitsverzeichnis

Im Folgenden Beispiel erklärt gut es ausdr.

#!/usr/bin/perl 
use strict; 
use warnings; 
use File::Basename; 
use Cwd; 

my $scriptDir = dirname($0); 
chdir($scriptDir); 
print "First: $scriptDir\n"; 
$scriptDir = getcwd(); 
print "Second: $scriptDir\n"; 

Ausgang:

[email protected]:~/Desktop$ perl test.pl 
First: . 
Second: /home/chankeypathak/Desktop 
0

Ich bin nicht die nächste Perl Monger, aber ich habe versucht, den Code auszuführen Sie mit einem kleinen Skript gaben:

#!/usr/bin/perl 
# 

use strict; 
use File::Basename; 
use Cwd; 

BEGIN { 
    my $scriptDir = dirname($0); 
    print "scriptDir = $scriptDir\r\n"; 
    chdir($scriptDir); 
    $scriptDir = getcwd(); 
    print "scriptDir = $scriptDir\r\n"; 
} 

Und das ist, was kam heraus:

[email protected]:~/perltest> ./script.pl 
scriptDir = . 
scriptDir = /home/map/perltest 
[email protected]:~/perltest> 

Es lo Ok, als ob dirname und getcwd in diesem Fall einen Unterschied machen. Wenn jedoch scrip.pl in Weg gefunden wird, gibt es keinen Unterschied:

[email protected]:~> cp script.pl ~/bin 
[email protected]:~> cd 
[email protected]:~> script.pl 
scriptDir = /home/map/bin 
scriptDir = /home/map/bin 
[email protected]:~> rm ~/bin 
Verwandte Themen