nie znaleziono polecenia realpath

24

Mam debian squeeze amd64. Moja obecna powłoka to bash. Jeśli napiszę w moim terminalu, to działa:

$ uname -a
Linux core 2.6.32-5-amd64 #1 SMP Fri May 10 08:43:19 UTC 2013 x86_64 GNU/Linux
$ echo $SHELL
/bin/bash                                                                                                                                                                                     
$ echo $(realpath test.sh)                                                                                                                                                     
/home/ffortier/test.sh

Mój plik test.sh wygląda następująco:

#!/bin/bash
echo $(realpath "$1")

Jeśli spróbuję wykonać następujące czynności, pojawia się błąd

$ ./test.sh test.sh 
./test.sh: line 2: realpath: command not found

Jak mogę użyć polecenia realpath w pliku bash?

Dodatkowe informacje

$ type -a realpath
realpath is a function                                                                                                                                                                        
realpath ()                                                                                                                                                                                   
{                                                                                                                                                                                             
    f=$@;                                                                                                                                                                                     
    if [ -d "$f" ]; then                                                                                                                                                                      
        base="";                                                                                                                                                                              
        dir="$f";                                                                                                                                                                             
    else                                                                                                                                                                                      
        base="/$(basename "$f")";                                                                                                                                                             
        dir=$(dirname "$f");                                                                                                                                                                  
    fi;                                                                                                                                                                                       
    dir=$(cd "$dir" && /bin/pwd);                                                                                                                                                             
    echo "$dir$base"                                                                                                                                                                          
}           
Francis
źródło

Odpowiedzi:

9

Czy realpath to rzeczywiste polecenie lub skrypt? Sprawdziłbym, skąd pochodzi.

$ type -a realpath

Nie znam tego narzędzia, więc prawdopodobnie nie jest ono częścią Twojej normalnej dystrybucji, być może jest ono zainstalowane w niestandardowej lokalizacji, która nie jest obecna w Bash, $PATHale znajduje się w środowisku logowania $PATH.

W każdym razie powyższe typepolecenie pokaże, skąd ono pochodzi, i wtedy możesz zmienić metodę, którą wywołujesz w skrypcie, w następujący sposób:

echo $(/path/to/realpath test.sh)

Lub zmień skrypty, $PATHaby obejmowały także tę niestandardową lokalizację.

Funkcje w powłoce

Większość twojego środowiska nie jest wywoływana, gdy wywołujesz skrypt powłoki. Jeśli się nad tym zastanowić, ma to sens, ponieważ generalnie nie chcesz, aby skrypty zawierały cały dodatkowy bagaż, jaki może mieć środowisko użytkownika.

Możesz albo określić, który plik źródłowy udostępnia tę funkcję, albo dowolne źródło, lub po prostu poinstruować Bash, aby uwzględnił twoje środowisko logowania.

#!/bin/bash -l
echo $(realpath "$1")
slm
źródło
Jest to funkcja, patrz edycja
Francis
@Francis - tak, funkcje nie są uwzględniane podczas wywoływania skryptu. Będziesz musiał je zdobyć, jeśli chcesz, żeby przyszły. Dowiedz się, który plik pełni tę funkcję, i zgłoś go. Jeśli chcesz tylko całą env. następnie zmienić swoje wezwanie do bash #!/bin/bash -l.
slm
Jak mogę dowiedzieć się, skąd pochodzi ta funkcja?
Francis
1
@mikeserv - dzięki, kiedy to napisałem, nadal korzystałem z Fedory 14, która nie została uwzględniona realpath. Mój system Fedora 19 zawiera teraz to narzędzie. Zauważ też, że OP używa jądra Debian w / 2.6, więc jego systemu też by brakowało, realpathbiorąc pod uwagę jego wiek.
slm
1
@mikeserv - tak, byłem zaskoczony, to jest teraz stare Q, ale informacje o nim commandbyły dla mnie przydatne. To bardziej przenośny sposób na robienie tego, co pokazywałem w powłokach POSIX.
slm
27

Istnieją co najmniej dwa programy o nazwie realpath:

  • Stary program z przeszłości, gdy nie zawierał jądra GNU readlink -f. Jest teraz przestarzałe na korzyść readlink -f, więc wiele dystrybucji przestało go nosić.
  • realpathProgram wprowadzony w GNU Coreutils 8.15. Jest to za stary, aby można go było ściskać w Debianie, a nawet świst; podczas pisania Debian niestabilny też go nie wysyła . Ten program jest bardzo blisko readlink -f.

Z jakiegoś powodu masz funkcję powłoki, która częściowo emuluje zachowanie realpath. Ta emulacja jest częściowa: jeśli wywołasz ją na dowiązaniu symbolicznym, nie będzie ona podążać za dowiązaniem symbolicznym.

Ponieważ jest to funkcja powłoki, prawdopodobnie załadowana z lub przez .bashrc, jest dostępna tylko dla kodu działającego w interaktywnej powłoce. Jeśli chcesz, aby był dostępny dla innych programów, zakładając, że używasz Linuksa, utwórz skrypt emulujący realpath:

#!/bin/sh
readlink -f -- "$@"

(To nie emuluje realpathrzadko używanych opcji wiersza poleceń.)

Gilles „SO- przestań być zły”
źródło
2
Nie mogę znaleźć żadnych dowodów w git repo coreutils, że realpathprogram jest uważany za przestarzały przez coreutils lub że nie jest zbudowany domyślnie. Więc Debian musi go usuwać.
Kaz
@Kaz No cóż, tylko dla uproszczenia, coreutils niedawno (8.15) wprowadził plik realpathbinarny, który jest bliski, ale nie do końca identyczny readlink -f. Stabilna Debiana przenosi 8.13. Niestabilny Debian zdecydował się zachować starszy program .
Gilles „SO- przestań być zły”
To nie było tak niedawno - był styczeń 2012. savannah.gnu.org/forum/forum.php?forum_id=7076
mikeserv
1
@mikeserv Zdecydowanie za późno na dystrybucję w pytaniu (ściśnięcie Debiana). Nawet zbyt aktualne dla obecnej stabilnej wersji Debiana.
Gilles „SO- przestań być zły”
To trochę przerażające. Ile lat ma ich openssl?
mikeserv
8

Działa tylko w powłoce, ponieważ plik skryptu ma inny zasięg i nie ma dostępu do lokalnych funkcji i aliasów zdefiniowanych w plikach rc . A realpathpolecenie faktycznie nie istnieje w twoim systemie.

Więc zainstaluj realpathz pakietu, zdefiniuj własną funkcję (jako część skryptu, sprawdź kilka przykładów ) lub źródłowy plik rc w skrypcie, w którym jest zdefiniowany (np . ~/.bashrc.).


Oto kroki, które należy zainstalować, realpathjeśli go nie ma:

  • Ubuntu: sudo apt-get install coreutils
  • OS X: brew install coreutils

Ubuntu i Debian

Na Debianie lub Ubuntu wydaje się, że realpathpowinna być instalowana domyślnie. Sprawdziłem najnowszą wersję Debian 8 (Jessie) i wygląda na to, że została coreutilsdomyślnie zainstalowana.

Testowane przy użyciu świeżych obrazów maszyn wirtualnych:

$ vagrant init debian/jessie64 && vagrant up --provider virtualbox && vagrant ssh
$ vagrant init ubuntu/vivid64 && vagrant up --provider virtualbox && vagrant ssh

Następnie w maszynie wirtualnej:

$ type -a realpath
realpath is /usr/bin/realpath

Zamiast tego realpathmożesz również użyć readlink -f file(lub greadlink) dostarczonego przez coreutilspakiet.

kenorb
źródło
5
$ sudo apt-get install realpath
użytkownik175315
źródło