Chciałbym znaleźć sposób dodania rzeczy do $ PATH, dla całego systemu lub dla pojedynczego użytkownika, bez potencjalnego wielokrotnego dodawania tej samej ścieżki.
Jednym z powodów, dla których warto to zrobić, jest dodanie dodatków .bashrc
, które nie wymagają logowania, a także są bardziej przydatne w systemach, które używają (np.) lightdm
, Które nigdy nie wywołuje .profile
.
Zdaję sobie sprawę z pytań dotyczących usuwania duplikatów z $ PATH, ale nie chcę ich usuwać . Chciałbym sposób dodawać ścieżki tylko wtedy, gdy nie są one już obecne.
Odpowiedzi:
Załóżmy, że nowa ścieżka, którą chcemy dodać, to:
Następnie za pomocą dowolnej powłoki POSIX możemy sprawdzić, czy
new
jest już na ścieżce i dodać ją, jeśli nie jest:Zwróć uwagę na użycie dwukropków. Bez dwukropków moglibyśmy pomyśleć, że powiedzmy, że
new=/bin
był już na ścieżce, ponieważ wzór pasował do siebie/usr/bin
. Chociaż ŚCIEŻKI zwykle zawierają wiele elementów, obsługiwane są również specjalne przypadki zer i jeden element ŚCIEŻKI. Sprawa ŚCIEŻKI początkowo nieposiadająca elementów (pusta) jest obsługiwana przez użycie${PATH:=$new}
przypisaniaPATH
do,$new
jeśli jest pusta. Ustawienie wartości domyślnych parametrów w ten sposób jest cechą wszystkich powłok POSIX: patrz sekcja 2.6.2 dokumentacji POSIX .)Funkcja wywoływalna
Dla wygody powyższy kod można wprowadzić w funkcję. Tę funkcję można zdefiniować w wierszu poleceń lub, aby była dostępna na stałe, umieścić w skrypcie inicjującym powłokę (dla użytkowników bash
~/.bashrc
):Aby użyć tej funkcji aktualizacji ścieżki, aby dodać katalog do bieżącej ŚCIEŻKI:
źródło
PATH
jest pusty, doda to pusty wpis (tj. Bieżący katalog) doPATH
. Myślę, że potrzebujesz innej skrzynki.case
. Po prostu zróbcase "${PATH:=$new}"
. Zobacz moją odpowiedź na podobne awarie.Utwórz plik o
/etc/profile.d
nazwie np.mypath.sh
(Lub cokolwiek chcesz). Jeśli używasz lightdm, upewnij się, że jest to wykonalne, w przeciwnym razie użyj/etc/bashrc
lub plik pochodzący z tego samego. Dodaj do tego następujące funkcje:Rzeczy na początku (poprzedzone) $ PATH mają pierwszeństwo przed tym, co następuje, i odwrotnie, rzeczy na końcu (dołączone) zostaną zastąpione przez to, co nastąpi wcześniej. Oznacza to, że jeśli $ PATH jest
/usr/local/bin:/usr/bin
i istnieje plik wykonywalnygotcha
w obu katalogach,/usr/local/bin
domyślnie zostanie użyty ten w.Możesz teraz - w tym samym pliku, w innym pliku konfiguracyjnym powłoki lub z wiersza poleceń - użyć:
Jeśli jest to w
.bashrc
, zapobiegnie to pojawianiu się wartości więcej niż raz podczas uruchamiania nowej powłoki. Istnieje ograniczenie polegające na tym, że jeśli chcesz dołączyć coś, co zostało wcześniej przygotowane (tj. Przesunąć ścieżkę w obrębie $ PATH) lub odwrotnie, musisz to zrobić sam.źródło
$PATH
zIFS=:
ostatecznie jest bardziej elastyczny niżcase
.case
IMO. Wyobrażam sobie,awk
że tutaj też można by dobrze wykorzystać.gawk
można bezpośrednio przypisać$PATH
.Możesz to zrobić w ten sposób:
Uwaga: jeśli budujesz PATH z innych zmiennych, sprawdź, czy nie są one puste, ponieważ wiele powłok interpretuje „„ jak ”. .
źródło
-q
POSIX jest wymagany przez grep, ale nie wiem, czy to oznacza, że nadal istnieją niektóre (nie POSIX) grep, które go nie mają./my/bin
Ważną częścią kodu jest sprawdzenie, czy
PATH
zawiera określoną ścieżkę:To znaczy, upewnij się, że każda ścieżka wewnątrz
PATH
jest oddzielona po obu stronachPATH
separatorem (:
), a następnie sprawdź (-q
), czy istnieje literalny ciąg (-F
) składający się zPATH
separatora, twojej ścieżki i innegoPATH
separatora. Jeśli nie, możesz bezpiecznie dodać ścieżkę:Powinno to być zgodne z POSIX i powinno działać z każdą ścieżką niezawierającą znaku nowej linii. Jest bardziej skomplikowany, jeśli chcesz, aby działał ze ścieżkami zawierającymi znak nowej linii, a jednocześnie jest zgodny z POSIX, ale jeśli masz
grep
obsługę-z
, możesz z niego korzystać.źródło
Od lat noszę tę małą funkcję w różnych
~/.profile
plikach. Myślę , że został napisany przez sysadmina w laboratorium, w którym kiedyś pracowałem, ale nie jestem pewien. W każdym razie jest podobny do podejścia Goldilocka, ale nieco inny:Aby dodać nowy katalog na początku
PATH
:i do końca:
źródło
/bin/grep
->grep
AKTUALIZACJA:
Zauważyłem, że twoja własna odpowiedź ma osobną funkcję do dodawania lub dodawania do
$PATH
. Podobał mi się ten pomysł. Dodałem więc trochę obsługi argumentów. Poprawnie_
ją też umieściłem:WYDAJNOŚĆ:
Domyślnie będzie to
-A
wskazywać na$PATH
, ale możesz zmienić to zachowanie, aby-P
naprawić, dodając-P
dowolne miejsce na liście argumentów. Możesz przełączyć go z powrotem na-A
dozowanie, wręczając go-A
ponownie.BEZPIECZNY EVAL
W większości przypadków zalecam, aby ludzie unikali jakiegokolwiek użycia
eval
. Ale to, jak sądzę, wyróżnia się na przykład na dobre. W tym przypadku jedynym stwierdzeniem,eval
jakie kiedykolwiek można zobaczyć, jestP=
lubA=
. Wartości jego argumentów są ściśle sprawdzane przed wywołaniem. Po toeval
jest.To przyjmie tyle argumentów, ile podasz, i dodasz każdy z nich
$PATH
tylko raz i tylko wtedy, gdy jeszcze go nie ma$PATH
. Wykorzystuje tylko w pełni przenośny skrypt powłoki POSIX, opiera się tylko na wbudowanych powłokach i jest bardzo szybki.źródło
_
prefiksowanie funkcji powłoki powoduje, że są one odpowiednio rozmieszczone? W innych językach zwykle oznacza wewnętrzną funkcję globalną (to znaczy taką, która musi być globalna, ale nie jest przeznaczona do użytku zewnętrznego jako część interfejsu API). Moje imiona z pewnością nie są świetnymi wyborami, ale wydaje mi się, że samo użycie_
wcale nie rozwiązuje problemów z kolizją - lepiej byłoby podać rzeczywistą przestrzeń nazw, np.mikeserv_path_assign()
._
, musisz zmienić menedżera pakietów. W każdym razie jest to po prostu „globalna, wewnętrzna funkcja” - jest globalna dla każdej powłoki wywoływanej z powłoki, w której została zadeklarowana, i jest tylko odrobiną zinterpretowanego skryptu językowego wiszącego w pamięci tłumacza . unix.stackexchange.com/questions/120528/…unset a
(lub odpowiednik) na końcu profilu?Ujrzeć! Wytrzymała przemysłowa 12-liniowa ... technicznie przenośna powłoka bash i zsh, która z oddaniem uwielbia wybrany przez Ciebie skrypt startowy
~/.bashrc
lub~/.zshrc
startowy:Przygotujcie się na natychmiastową chwałę. Następnie, zamiast robić to i życzyć sobie najlepszego:
Zrób to zamiast tego i zapewnij sobie to, co najlepsze, niezależnie od tego, czy naprawdę tego chcesz, czy nie:
Bardzo dobrze, określ „Najlepsze”.
Bezpieczne dołączanie i dopływanie do prądu
${PATH}
nie jest banalną sprawą, na którą zwykle się składa. Choć wygodne i pozornie rozsądne, jednowarstwowe formyexport PATH=$PATH:~/opt/bin
zachęcają do diabelskich komplikacji z:Przypadkowe nazwy względne (np
export PATH=$PATH:opt/bin
.). Podczas gdybash
izsh
po cichu akceptuję i najczęściej ignoruję względne nazwy w większości przypadków, względne nazwy poprzedzone jednymh
lubt
(i prawdopodobnie innymi nikczemnymi bohaterami) powodują, że oba wstydliwie okaleczają się jako przełomowe arcydzieło Masakiego Kobayashiego z 1962 r. Harakiri :Przypadkowo zduplikowane nazwy. Chociaż zduplikowane
${PATH}
nazwy są w dużej mierze nieszkodliwe, są również niepożądane, nieporęczne, nieco nieefektywne, utrudniają debuggowanie i promują zużycie dysku - coś w rodzaju takiej odpowiedzi. Podczas gdy dyski SSD w stylu NAND są ( oczywiście ) odporne na zużycie odczytu, dyski HDD nie są. Niepotrzebny dostęp do systemu plików przy każdej próbie polecenia oznacza niepotrzebne zużycie głowicy odczytu w tym samym tempie. Duplikaty są szczególnie nieprzyjemne, gdy wywołuje się zagnieżdżone skorupy w zagnieżdżonych podprocesach, w których to pozornie nieszkodliwe jednowarstwowe, jakexport PATH=$PATH:~/wat
szybko, eksplodują w Siódmym Kręgu${PATH}
PiekłaPATH=/usr/local/bin:/usr/bin:/bin:/home/leycec/wat:/home/leycec/wat:/home/leycec/wat:/home/leycec/wat
. Tylko Belzebubba może ci pomóc, jeśli do tego dodasz dodatkowe nazwy. (Nie pozwól, aby stało się to z twoimi cennymi dziećmi. )${PATH}
nazwy są w dużej mierze nieszkodliwe, zazwyczaj są one również niepożądane, nieporęczne, lekko nieefektywne, utrudniają debuggowanie i sprzyjają zużyciu dysku.Ergo, przyjazna automatyzacja, taka jak funkcja powłoki zdefiniowana powyżej. Musimy uratować się od siebie.
Ale ... Dlaczego „+ path.append ()”? Dlaczego nie po prostu append_path ()?
Dla disambiguity (na przykład za pomocą poleceń zewnętrznych obecnych
${PATH}
lub na cały system funkcji powłoki zdefiniowane gdzie indziej), funkcje powłoki zdefiniowane przez użytkownika są idealnie przedrostkiem lub przyrostkiem unikalnych podciągów obsługiwanych przezbash
izsh
a, które są zabronione w standardzie basenames poleceń - takich jak, na przykład,+
.Hej. To działa. Nie osądzaj mnie.
Ale ... Dlaczego „+ path.append ()”? Dlaczego nie „+ path.prepend ()”?
Ponieważ
${PATH}
dopływ do prądu jest bezpieczniejszy niż dopływ do prądu${PATH}
, wszystkie rzeczy są równe, którymi nigdy nie są. Zastępowanie poleceń systemowych za pomocą poleceń specyficznych dla użytkownika może być w najlepszym razie niehigieniczne, aw najgorszym stanie się szaleństwem. Na przykład w systemie Linux aplikacje podrzędne zwykle oczekują wariantów poleceń GNU coreutils , a nie niestandardowych niestandardowych pochodnych lub alternatyw.To powiedziawszy, istnieją absolutnie uzasadnione przypadki użycia. Zdefiniowanie równoważnej
+path.prepend()
funkcji jest banalne. Sans prolix mgławica, bo on i jej wspólny rozsądek:Ale ... dlaczego nie Gilles?
Gilles ' Akceptowane odpowiedź gdzie indziej jest imponująco optymalna w ogólnym przypadku jako «shell agnostycznego idempotent append» . W przypadku wspólnego
bash
izsh
ze bez niepożądanych dowiązania jednak kara wydajność wymaga tego smuci się Ricer Gentoo we mnie. Nawet w obecności niepożądanych dowiązań symbolicznych można zastanawiać się, czy rozwidlenie jednej podpowłoki naadd_to_PATH()
argument jest warte potencjalnego wstawienia duplikatów dowiązań symbolicznych.W przypadku ścisłych przypadków użycia, wymagających wyeliminowania nawet duplikatów dowiązań symbolicznych, ten
zsh
wariant specyficzny robi to za pomocą wydajnych wbudowanych elementów zamiast nieefektywnych rozwidleń:Uwaga
*":${dirname:A}:"*
raczej niż*":${dirname}:"*
oryginał.:A
jest cudowny -zsh
niestety nieobecny pod większością innych powłok - w tymbash
. Cytującman zshexpn
:Żadnych dalszych pytań.
Nie ma za co. Ciesz się bezpiecznym ostrzałem. Zasługujesz teraz na to.
źródło
Oto moja wersja w stylu programowania funkcjonalnego.
*PATH
zmienną rozdzielaną dwukropkami , nie tylkoPATH
.Na uwagę zasługuje również:
export
ing; pozostawiono to dzwoniącemu (patrz przykłady)bash
; bez rozwidleniaźródło
Ten skrypt umożliwia dodanie na końcu
$PATH
:Lub dodaj na początku
$PATH
:źródło