2011-01-26 6 views
5

Tôi đang tìm kiếm một cách để có được hai mẩu thông tin:Perl - Tôi có thể nhận được các đường dẫn liên quan đến nơi một tập lệnh cư trú và nơi nó được thực hiện từ đâu không?

  • Các đường dẫn đầy đủ về nơi cư trú một kịch bản bao gồm tên tập tin của nó
  • Các đường dẫn đầy đủ về nơi một kịch bản đã được thực hiện từ

Tôi biết bạn có thể sử dụng $0 để có được tên tệp, nhưng có bất kỳ biến dành riêng khác có nguồn gốc Perl mà sẽ cho tôi những gì tôi đang tìm kiếm không?

Tôi không muốn sử dụng bất kỳ mô-đun đặc biệt nào, nhưng nếu đó là cách duy nhất, thì hãy làm như vậy.

+3

"Tôi không muốn sử dụng bất kỳ các module đặc biệt" -- tại sao? Lưu ý rằng có rất nhiều mô-đun đi kèm với phân phối perl. – Ether

+0

@ether - vì lý do tương tự tôi không thích sốt cà chua trên hotdogs tôi giả sử – CheeseConQueso

Trả lời

2

biến môi trường PWD giữ thư mục làm việc hiện tại, đây là đường dẫn tập lệnh được thực hiện từ đó.

Bạn có thể lấy đường dẫn đầy đủ của kịch bản với $ENV{PWD}$0

Sửa: cung cấp mẫu mã vì nó là khó khăn cho một số người tin rằng điều này là có thể:

Tôi có thể không bắt tất cả các trường hợp có thể, nhưng điều này sẽ nhận được rất gần:

use strict; 
use warnings; 

print "PWD: $ENV{PWD}\n"; 
print "\$0: $0\n"; 

my $bin = $0; 
my $bin_path; 

$bin =~ s#^\./##; # removing leading ./ (if any) 

# executed from working directory 
if ($bin !~ m#^/|\.\./#) { 
    $bin_path = "$ENV{PWD}/$bin"; 
} 
# executed with full path name 
elsif ($bin =~ m#^/#) { 
    $bin_path = $0; 
} 
# executed from relative path 
else { 
    my @bin_path = split m#/#, $bin; 
    my @full_path = split m#/#, $ENV{PWD}; 

    for (@bin_path) { 
    next if $_ eq "."; 
    ($_ eq "..") ? pop @full_path : push @full_path, $_; 
    } 
    $bin_path = join("/", @full_path); 
} 

print "Script Path: $bin_path\n"; 

Output từ thử nghiệm chạy:

012.
PWD: /tmp 
$0: ../home/cmatheson/test.pl 
Script Path: /home/cmatheson/test.pl 

PWD: /home/cam 
$0: ./test.pl 
Script Path: /home/cam/test.pl 

PWD: /usr/local 
$0: /home/cam/test.pl 
Script Path: /home/cam/test.pl 

PWD: /home/cam/Desktop/foo 
$0: ../../src/./git-1.7.3.2/../../test.pl 
Script Path: /home/cam/test.pl 
+0

oh yeah .... tôi thậm chí không nghĩ về điều đó. cảm ơn. câu hỏi duy nhất tôi có về điều đó là nếu cron chạy kịch bản, nó sẽ vẫn hoạt động? – CheeseConQueso

+4

'$ PWD' chứa thư mục làm việc hiện tại của tập lệnh chứ không phải vị trí của tập lệnh. Ví dụ, cwd của tôi có thể là '~' nhưng tập lệnh có thể nằm trong '/ usr/bin'. – Ether

+2

@cam: _does_ này trả lời phần thứ hai của câu hỏi - nơi tập lệnh được thực thi từ đó. Tuy nhiên, điều này không thể được sử dụng để tìm đường dẫn đến vị trí của tập lệnh. Loại bỏ câu cuối cùng. – maxelost

3
use File::Spec; 

print File::Spec->rel2abs($0); 

in đường dẫn đầy đủ đến tập lệnh của bạn bao gồm tên tệp như bạn muốn.

+0

cảm ơn boong - bệnh kiểm tra nó ra – CheeseConQueso

0

Bạn có thể sử dụng các mô-đun lõi Cwd để có được những thư mục mà từ đó các kịch bản đã được thực hiện, và các mô-đun lõi File::Spec để tìm toàn bộ đường dẫn đến kịch bản:

#!perl 

use strict; 
use warnings; 
use Cwd; 
use File::Spec; 

my $dir = getcwd(); 
print "Dir: $dir\n"; 

print "Script: " . File::Spec->rel2abs($0) . "\n"; 
+0

'getcwd()' trả về thư mục làm việc hiện tại của tập lệnh, không phải vị trí của tập lệnh. Ví dụ, cwd của tôi có thể là '~' nhưng tập lệnh có thể nằm trong '/ usr/bin'. – Ether

+0

Tôi lấy "Con đường đầy đủ của nơi mà một kịch bản được thực hiện từ" để có nghĩa là "con đường mà tôi đã được khi tôi thực hiện kịch bản". – CanSpice

+0

bạn là chính xác canspice, tôi muốn biết con đường mà tôi đã được khi tôi thực hiện kịch bản. ngoài ra, tôi muốn biết chính kịch bản sống ở đâu – CheeseConQueso

2

này có sẵn với các built- trong biến $ FindBin :: Bin (xem perldoc FindBin):

use FindBin; 
use File::Spec; 

print "the location of my script is: ", $FindBin::Bin, "\n"; 
print "the basename of my script is: ", $FindBin::Script, "\n"; 
print "the full path (symlinks resolved) of my script is: ", File::Spec->catfile($FindBin::RealBin, $FindBin::RealScript), "\n"; 
7

Sử dụng FindBinCwd:

#!/usr/bin/env perl 

use strict; 
use warnings; 

use Cwd  (); 
use FindBin (); 
use File::Spec(); 

my $full_path = File::Spec->catfile($FindBin::Bin, $FindBin::Script); 
my $executed_from_path = Cwd::getcwd(); 

print <<OUTPUT; 
Full path to script: $full_path 
Executed from path: $executed_from_path 
OUTPUT 

Mẫu đầu ra (script lưu lại dưới dạng /tmp/test.pl):

[email protected]:/usr/share$ /tmp/test.pl 
Full path to script: /tmp/test.pl 
Executed from path: /usr/share 
1

Bạn hỏi về đặc biệt thứ Perl và không có ai có đề cập __FILE__. Kiểm tra perldata cho nó và hơn thế nữa. Tôi sử dụng thành ngữ này thường khi tôi có một cây con có liên quan của các file/scripts/modules-

use Path::Class qw(file); 
use File::Spec; 

my $self_file = file(File::Spec->rel2abs(__FILE__)); 
print 
    " Full path: $self_file", $/, 
    "Parent dir: ", $self_file->parent, $/, 
    " Just name: ", $self_file->basename, $/; 
2

Đối với một giải pháp mà cũng xử lý liên kết tượng trưng, ​​

use Cwd   qw(realpath); 
use File::Basename qw(dirname); 

# Look for modules in the same dir as the script. 
use lib dirname(realpath($0));