Mam skrypt Perl i muszę określić pełną ścieżkę i nazwę pliku skryptu podczas wykonywania. Odkryłem, że w zależności od tego, jak wywołasz skrypt, $0
różni się i czasami zawiera, fullpath+filename
a czasami po prostu filename
. Ponieważ katalog roboczy również może się różnić, nie mogę wymyślić sposobu na niezawodne pobranie fullpath+filename
skryptu.
Czy ktoś ma rozwiązanie?
__FILE__
) nie działa zgodnie z oczekiwaniami? W końcu otrzymuję ścieżkę względną, z której skrypt został wykonany, podczas gdy zaakceptowana odpowiedź daje mi pełną ścieżkę bezwzględną.dirname(__FILE__)
nie podąża za dowiązaniami symbolicznymi, więc jeśli połączyłeś plik wykonywalny i gdzie masz nadzieję znaleźć lokalizację innego pliku w lokalizacji instalacji, musisz sprawdzić,if( -l __FILE__)
a następniedirname(readlink(__FILE__))
.perl -e 'use Module::CoreList; print Module::CoreList->first_release("File::Basename");'; echo
. ToFile::Basename
był Perl 5.0.0, który został wydany pod koniec lat 90-tych - myślę, że teraz jest bezpieczny.0 $ to zazwyczaj nazwa twojego programu, więc co powiesz na to?
Wydaje mi się, że powinno to działać tak, jak abs_path wie, czy używasz ścieżki względnej czy bezwzględnej.
Aktualizacja Każdy, kto czyta to lata później, powinien przeczytać odpowiedź Drew . Jest dużo lepsze niż moje.
źródło
realpath
, co jest synonimemabs_path
, jeśli wolisz nazwę bez podkreśleniaperl -e 'use Cwd "abs_path";print abs_path($0);'
wydruki/tmp/-e
-e
), wydaje mi się, że Perl tworzy plik tymczasowy do przechowywania skryptu wbudowanego. Wygląda na to, że w twoim przypadku lokalizacja to/tmp
. Jaki będzie wynik?http://perldoc.perl.org/File/Spec/Unix.html
źródło
Myślę, że moduł, którego szukasz, to FindBin:
źródło
Możesz użyć FindBin , Cwd , File :: Basename lub ich kombinacji. Wszystkie znajdują się w podstawowej dystrybucji Perl IIRC.
W przeszłości korzystałem z Cwd:
Cwd:
źródło
Uzyskanie absolutnej ścieżki do
$0
lub__FILE__
jest tym, czego chcesz. Jedynym problemem jest to, że jeśli ktoś zrobił a,chdir()
a$0
był względny - wtedy musisz uzyskać absolutną ścieżkę w aBEGIN{}
aby uniknąć niespodzianek.FindBin
próbuje pójść o jeden lepszy i czołgać się w$PATH
poszukiwaniu czegoś pasującego dobasename($0)
, ale są chwile, kiedy robi to zbyt zaskakujące rzeczy (w szczególności: gdy plik znajduje się „tuż przed tobą” w cwd).File::Fu
maFile::Fu->program_name
iFile::Fu->program_dir
do tego.źródło
chdir()
w czasie kompilacji?Krótkie tło:
Niestety, Unix API nie zapewnia działającego programu z pełną ścieżką do pliku wykonywalnego. W rzeczywistości program wykonujący twój może dostarczyć wszystko, czego chce, w polu, które normalnie mówi twojemu programowi, czym to jest. Jak wskazują wszystkie odpowiedzi, istnieją różne heurystyki służące do znajdowania prawdopodobnych kandydatów. Ale nic poza przeszukiwaniem całego systemu plików zawsze będzie działać, a nawet to się nie powiedzie, jeśli plik wykonywalny zostanie przeniesiony lub usunięty.
Ale nie chcesz pliku wykonywalnego Perla, który faktycznie działa, ale skrypt, który wykonuje. Perl musi wiedzieć, gdzie skrypt ma go znaleźć. Przechowuje to w
__FILE__
, podczas gdy$0
pochodzi z Unix API. To wciąż może być ścieżka względna, więc skorzystaj z sugestii Marka i kanonizuj jąFile::Spec->rel2abs( __FILE__ );
źródło
__FILE__
nadal daje mi względną ścieżkę. ie „.”.Czy próbowałeś:
lub
To naprawdę zależy od tego, jak jest nazywany i czy jest to CGI, czy jest uruchamiany z normalnej powłoki itp.
źródło
Aby uzyskać ścieżkę do katalogu zawierającego mój skrypt, użyłem kombinacji udzielonych już odpowiedzi.
źródło
perlfaq8 odpowiada na bardzo podobne pytanie, używając
rel2abs()
funkcji on$0
. Tę funkcję można znaleźć w File :: Spec.źródło
Nie ma potrzeby korzystania z zewnętrznych modułów, wystarczy jedna linia, aby podać nazwę pliku i ścieżkę względną. Jeśli używasz modułów i chcesz zastosować ścieżkę względną do katalogu skryptów, wystarczy ścieżka względna.
źródło
: DD
źródło
Szukasz tego ?:
Wynik będzie wyglądał następująco:
Działa zarówno w systemie Windows, jak i Unix.
źródło
źródło
Problem
__FILE__
polega na tym, że wypisze ścieżkę do modułu podstawowego „.pm”, niekoniecznie ścieżkę skryptu „.cgi” lub „.pl”, który jest uruchomiony. Myślę, że to zależy od tego, jaki jest twój cel.Wydaje mi się, że
Cwd
wystarczy zaktualizować mod_perl. Oto moja sugestia:Dodaj wszelkie sugestie.
źródło
Bez żadnych zewnętrznych modułów, ważne dla powłoki, działa dobrze nawet z '../':
test:
źródło
Problem z samym użyciem
dirname(__FILE__)
polega na tym, że nie podąża za dowiązaniami symbolicznymi. Musiałem użyć tego, aby mój skrypt podążał za dowiązaniem symbolicznym do rzeczywistej lokalizacji pliku.źródło
Wszystkie rozwiązania bez biblioteki nie działają na więcej niż kilka sposobów zapisania ścieżki (pomyśl ../ lub /bla/x/../bin/./x/../ itd. Moje rozwiązanie wygląda tak poniżej. Mam jedno dziwactwo: nie mam pojęcia, dlaczego muszę dwukrotnie uruchamiać zamienniki. Jeśli nie, otrzymuję fałszywy „./” lub „../”. Poza tym wydaje mi się dość mocny.
źródło
Żadna z „najpopularniejszych” odpowiedzi nie była dla mnie odpowiednia. Problem z używaniem FindBin '$ Bin' lub Cwd polega na tym, że zwracają one ścieżkę bezwzględną z rozwiązanymi wszystkimi dowiązaniami symbolicznymi. W moim przypadku potrzebowałem dokładnej ścieżki z obecnymi dowiązaniami symbolicznymi - tak samo, jak zwraca polecenie Unix "pwd", a nie "pwd -P". Następująca funkcja zapewnia rozwiązanie:
źródło
W systemie Windows najlepiej dla mnie działało używanie
dirname
iabs_path
razem.dlatego:
źródło
Co jest nie tak
$^X
?Zapewnia pełną ścieżkę do używanego pliku binarnego Perla.
Wynicować
źródło
Na * nix prawdopodobnie masz polecenie "whereis", które przeszukuje $ PATH w poszukiwaniu pliku binarnego o podanej nazwie. Jeśli $ 0 nie zawiera pełnej nazwy ścieżki, uruchomienie whereis $ scriptname i zapisanie wyniku w zmiennej powinno powiedzieć, gdzie znajduje się skrypt.
źródło