Czy tylda, `~` jest uważana za ścieżkę względną?

35

Próbuję wyodrębnić inną część instalatora biblioteki Nvidia cuda. Używam następującego polecenia:

mkdir ~/Downloads/nvidia_installers
./cuda_6.5.14_linux_64.run -extract=~/Downloads/nvidia_installers

I otrzymuję następujący komunikat:

ERROR: extract: path must be absolute.

A kiedy wpisuję polecenie z dosłownym adresem mojego domu, działa idealnie.

./cuda_6.5.14_linux_64.run -extract=/home/likewise-open/XXX/username/Downloads/nvidia_installers

Jestem zdezorientowany, czy ~ nie powinno być takie samo jak / home / podobnie-open / XXX / nazwa użytkownika?

Przetestowany:

./cuda_6.5.14_linux_64.run -extract=$HOME/Downloads/nvidia_installers

i działa, ale nie wiem, dlaczego to nie pozwala ~

Regan
źródło
2
Powiązane: „Przedrostek tyldy” składa się z niecytowanego znaku <tilde> na początku słowa, a następnie wszystkich znaków poprzedzających pierwszy bez cudzysłowu ”
Braiam

Odpowiedzi:

47

Bash rozwija ~, jeśli jest to początek słowa. Widać to między następującymi poleceniami:

$ echo -extract=~/test
-extract=~/test

oli@bert:~$ echo -extract ~/test
-extract /home/oli/test

Bash szuka osobnych ~znaków i ~/tej zamiany. Żadna inna kombinacja lub cytowana wersja nie będzie działać.

$HOMEdziała, ponieważ podstawienia zmiennych są bardziej niezawodne ( $jest to znak specjalny, podczas gdy ~jest o wiele mniej):

$ echo Thisisastring${HOME}awrawr
Thisisastring/home/oliawrawr

Podczas gdy mówimy ~, w rzeczywistości ma jeszcze kilka innych zastosowań zastępczych:

  • ~+bieżący katalog roboczy (odczyt z $PWD)
  • ~-poprzedni katalog roboczy (odczyt z $OLDPWD)

Tak jak w przypadku zwykłego ~, na końcu mogą znajdować się dodatkowe ścieżki, które ponownie muszą być przedrostkiem słowa, w przeciwnym razie Bash je zignoruje.

Możesz przeczytać więcej na ten temat w man bash | less -p ' Tilde'

Oli
źródło
2
Warto zauważyć, że zsh jest (a raczej może być skonfigurowany) rozwiń ~po =zbyt. Wśród innych wygodnych ulepszeń ma ponad bash.
Jan Hudec
@ JanHudec Nie - to bardziej skomplikowane; Nie chodzi o późniejsze rozwijanie =; chodzi o rozwinięcie na początku prawej strony przypisania zmiennej. To sprawia, że ​​nasza sprawa jest nieco bardziej zagmatwana, gdy się nam przyjrzy - patrz moja odpowiedź. I zshnie różni się od bashtego; Opis „zsh” jest nieco tajemniczy: info --subnodes zsh | less +/'14.7.4 Notes'(brakuje stron podręcznika Zsh)
Volker Siegel
1
@VolkerSiegel: zshjest bardzo konfigurowalny. W moim zsh echo -extract=~/testwyniki w -extract=/home/user/test. Jest włączony przez MAGIC_EQUAL_SUBSTopcje. Na marginesie, wszystkie strony podręcznika Zsh są w porządku.
Jan Hudec
@JanHudec Bez wątpienia zshkonfigurowalność - i inne ulepszenia; Spodziewałbym się, że MAGIC_EQUAL_SUBST (objęty 14.7.4) jest domyślnie wyłączony i rzadko używany; Teraz jest to oczywiście bardziej odpowiednie, jeśli masz ogólnie włączone. Po uzyskaniu mojej sekcji z przykładami w dobrej formie, byłby to miły dodatek ...
Volker Siegel
@JanHudec Jeśli chodzi o strony podręcznika Zsh, przez jakiś czas brakowało ich w pakietach Ubuntu, dzięki za podpowiedź nie wiedziałem, że zostało to naprawione; Patrząc na błąd, jest naprawiony na utopię, ale nie jest wiarygodny - to wyjaśnia! ( starter: brakuje wszystkich stron podręcznika Zsh i plików pomocy wbudowanej, a AU: brak człowieka Zsh ... )
Volker Siegel
19

Naprawiam to

To polecenie wyświetla komunikat o błędzie „BŁĄD: wyciąg: ścieżka musi być bezwzględna”:

./cuda_6.5.14_linux_64.run -extract=~/Downloads/nvidia_installers

Błąd nie jest pomocny - program był już zbyt zagubiony.
Wiesz już, że błąd pochodzi od ~, ponieważ $HOMEzamiast tego działa .

Problem: ~zostaje zastąpiony tylko na początku słowa.

Na przykład działa to z tyldą:

echo -extract ~/Downloads

Jeśli potrzebujesz składni opcji =, użycie $ HOME zamiast ~jest najbardziej czystym rozwiązaniem;

echo -extract=$HOME/Downloads

Praktyka

Co powinieneś wiedzieć:

Istnieją specjalne przypadki, w których ~get jest rozwijany, gdy nie jest na początku słowa: jako część przypisania zmiennej, bezpośrednio po =. Co oczywiście jest mylące.

Innym ważnym przypadkiem specjalnym jest użycie go ze zmiennymi takimi jak PATH. W przypisaniach zmiennych ~jest również rozwijany po :, podobnie jak po pierwszym =.

$ dir=~ sh -c 'echo D2: $dir'
D2: /home/user
$ sh -c 'echo D2: $dir' dir=~
D2: 
$ echo Dir: $dir
Dir:
$ dir=~; sh -c 'echo D2: $dir'
D2: 
$ echo Dir: $dir
Dir: /home/user
$ sh -c 'echo D2: $dir'; d3=~
D2: 
$ echo d3: $d3
d3: /home/user

Znaczenie tylda

W skorupie ~tylda nie jest tak naprawdę ścieżką. $HOMECzasami zastępuje ją tylko ścieżka .

Jest to coś w rodzaju skrótu lub skrótu, dostarczanego przez powłokę.
Nie można go używać jak ścieżki w ogóle, powłoka „rozszerza” ją na ścieżkę tylko w bardzo szczególnych miejscach.
I nawet jeśli jest rozwinięty, może być czymś innym niż katalog domowy.

  • Jest rozwijany tylko na początku słowa lub w zmiennej zmiennej po :lub=
  • Jest rozszerzany tylko wtedy, gdy nie znajduje się w cudzysłowie
  • Zostanie rozwinięty tylko $HOMEwtedy, gdy przed słowem nie będzie więcej znaków w słowie/

Problem w wierszu poleceń

Zgodnie z tym problem w twoim poleceniu polega na tym, że tylda się wchodzi

-extract=~/Downloads/nvidia_installers

nie jest rozwinięty, ponieważ nie jest to jeden z wymienionych przypadków. To wszystko.

Rozwiązaniem może być uczynienie tyldy pierwszym niecytowanym znakiem słowa, bez żadnego innego znaku przed następnym /- to właśnie otrzymujesz, gdy użyjesz opcji ze spacją przed argumentem opcji:

-extract ~/Downloads/nvidia_installers

Innym rozwiązaniem byłoby użycie $HOMEzamiast tego. W skrypcie jest to zwykle lepszy wybór.

-extract=$HOME/Downloads/nvidia_installers

Komunikat o błędzie

Ale jak wyświetla się komunikat o błędzie
"ERROR: extract: path must be absolute."?
zmieścisz się w tym wszystkim?

Wiemy, że tylda nie uległa rozszerzeniu. Oznacza to, że program otrzymał tekst argumentu zawierający ~, ale bez /home/auserścieżki jako. Ta ścieżka jest ~/Downloads/nvidia_installers- ale teraz nie ma powłoki, więc tylda nie ma specjalnego znaczenia. To tylko normalna nazwa katalogu. I jak każda inna ścieżka formy foo/bar/baz, jest to ścieżka względna

Inne zastosowania

Jeśli po ~, jak w ~alice- są znaki , jak w - z zachowaniem wszystkich powyższych zasad - i istnieją nazwy użytkowników alice, które alicezamiast tego są rozszerzone do katalogu domowego , powiedzmy home/alice.
Również, jeśli tak bob, ~rozwinąłby się /home/bobi ~bobrozwinąłby się do tego samego.

Wariant ~+zostanie rozszerzony do bieżącego katalogu,$PWD

Aby odnieść się do poprzedniego katalogu, w którym byłeś przed ostatnim cd, możesz użyć ~-, który jest rozwinięty do $OLDPWD.

Jeśli użyjesz, pushda popdzamiast cd, będziesz już wiedział, że można uzyskać dostęp do stosu katalogów jak ~-2.

Detale

Wszystkie przypadki, w których ~rozwinięto ścieżkę, są sprzedawane przez powłokę . W przypadku innych programów ~jest to zwykły znak nazwy pliku.

Dla dokładnej definicji wewnątrz skorupy, tutaj jest odpowiedni odcinek nocie jak zastąpienie przez to tylko jeden szczególny przypadek wielu przypadkach: „Jeśli ta nazwa logowania jest łańcuchem null, tylda zastępowana jest wartością parametru powłoki HOME. „ :man bash
~$HOME

Tilde Expansion
    If a word begins with an unquoted tilde character (`~'), all of the charac‐
    ters  preceding the first unquoted slash (or all characters, if there is no
    unquoted slash) are considered a tilde-prefix.  If none of  the  characters
    in  the tilde-prefix are quoted, the characters in the tilde-prefix follow‐
    ing the tilde are treated as a possible login name.  If this login name  is
    the  null string, the tilde is replaced with the value of the shell parame‐
    ter HOME.  If HOME is unset, the home directory of the user  executing  the
    shell is substituted instead.  Otherwise, the tilde-prefix is replaced with
    the home directory associated with the specified login name.

    If the tilde-prefix is a `~+', the value of the shell variable PWD replaces
    the  tilde-prefix.   If  the tilde-prefix is a `~-', the value of the shell
    variable OLDPWD, if it is set, is substituted.  If the characters following
    the tilde in the tilde-prefix consist of a number N, optionally prefixed by
    a `+' or a `-', the tilde-prefix is replaced with the corresponding element
    from  the  directory  stack,  as  it would be displayed by the dirs builtin
    invoked with the tilde-prefix as an argument.  If the characters  following
    the  tilde in the tilde-prefix consist of a number without a leading `+' or
    `-', `+' is assumed.

    If the login name is invalid, or the tilde expansion  fails,  the  word  is
    unchanged.

    Each variable assignment is checked for unquoted tilde-prefixes immediately
    following a : or the first =.  In these cases, tilde expansion is also per‐
    formed.   Consequently, one may use filenames with tildes in assignments to
    PATH, MAILPATH, and CDPATH, and the shell assigns the expanded value.
Volker Siegel
źródło
3

~nie jest ścieżką samą w sobie. Jest to znak, który otrzymuje specjalne traktowanie z powłoki, gdzie ~lub ~/oznacza „zamień na ścieżkę katalogu domowego bieżącego użytkownika”. ~usernameoznacza „zamień na ścieżkę katalogu domowego nazwy użytkownika”.

Ponieważ nie jest to ścieżka, jest rozpoznawana tylko w niektórych miejscach polecenia (jako pierwsza postać nowego tokena z podziałem spacji).

Po rozwinięciu został zastąpiony ścieżką bezwzględną.

Używanie $HOMEdziała, ponieważ HOME jest po prostu zmienną ustawioną przez powłokę i przestrzega normalnych reguł powłoki w celu zamiany zmiennych (dzieje się to przed podzieleniem danych wejściowych na spacje i wykonaniem).

Daenyth
źródło
1

Masz rację. ~ / Downloads to to samo, co / home / nazwa użytkownika / Downloads.

Niektórzy instalatorzy i ekstraktorzy są bardzo wybredni, jeśli chodzi o to, gdzie trzeba je umieścić. Myślę, że może tak być, ponieważ rejestruje ścieżki plików, a dzienniki nie będą akceptować ~ w przyjętej ścieżce.

Właśnie przyzwyczaiłem się do pisania w / home / username. :)

Dan Johansen
źródło