Czy wynik pwd to „~”?

28

pwd daje mi

/data/users/me/some/random/folder

Czy istnieje prosty sposób na uzyskanie?

~/some/random/folder

z pwd?

Hazard Sibbs
źródło
Czy przepuszczanie przez sed jest opcją?
Matthew D. Scholefield,
7
Jeśli masz zamiar to zrobić, zdecydowanie polecam nazwać wynikowe polecenie na coś innego niż pwd. W przeciwnym razie złamiesz skrypty, które oczekują użycia swoich wyników w kontekstach, które nie wykonują interpretacji tyldy.
Charles Duffy

Odpowiedzi:

25

Jeśli używasz bash, to dirswbudowane ma pożądane zachowanie:

dirs +0
~/some/random/folder

(Uwaga +0, nie-0 .)

Z zsh:

dirs
~/some/random/folder

Aby być dokładnie, najpierw musimy wyczyścić stos katalogów, w przeciwnym dirsrazie wydrukujemy całą zawartość:

dirs -c; dirs

Lub z zsh„s printwbudowanego polecenia:

print -rD $PWD

lub

print -P %~

(ten włącza szybkie rozszerzanie . %~in $PS1rozwija się do bieżącego katalogu z $HOMEzastąpionym przez, ~ale obsługuje również inne nazwane katalogi, takie jak katalog domowy innych użytkowników lub nazwane katalogi , które sam definiujesz).

chaos
źródło
Cały czas przełączam się między bash a zsh. Niestety to rozwiązanie zmusza mnie do zapamiętania różnicy między powłokami, a także do zapamiętania (sprawdzenia), gdzie aktualnie jestem. Odpowiedź @Bichoy jest niezależna od powłoki dla tych dwóch.
avp
18

Możesz użyć funkcji zamiany podciągów zmiennych Bash:

$ pwd
/home/vagrant/foo/bar
$ echo ${PWD/#$HOME/'~'}
~/foo/bar
Nykakin
źródło
2
Działa to również w kshi zsh.
mr.spuratic
1
Chociaż głosowałem za odpowiedzią na tę odpowiedź, ponieważ jest to najprostszy sposób, jest tutaj małe zastrzeżenie: wewnątrz / tmp / home / nazwa użytkownika, to zwróci / tmp ~. Nie mogę znaleźć sposobu, aby wstawić znak karetki przed $ HOME, aby to naprawić. Jeśli potrzebujesz, aby Twoje rozwiązanie było idealne, nie używaj tego ...
0fnt
1
@ user18151, niż ty za zwrócenie na to uwagi. Zastąpiłem swoją odpowiedź na ${string/#substring/replacement}wersję, aby temu zapobiec.
Nykakin
1
@ mr.spuratic jest poprawny (oprócz użycia echo) w zsh. W innych powłokach $HOMEbyłby traktowany jako wzór, a całość podlegałaby podziałowi + glob.
Stéphane Chazelas,
Ucieczka od tyldy ('~') załatwiła sprawę. Zauważ, że \ ~ również działa. Jest to wygodne, gdy już znajduje się w '-context: np.PROMPT_COMMAND='printf "\033]0;%s@%s:%s\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/\~}"'
Atafar
7

Używanie sed:

pwd | sed "s|^$HOME|~|"

Pomysł polega na użyciu dowolnego znaku, który rzadziej pojawia się w ścieżce katalogu domowego, jako ogranicznika w sedwyrażeniu regularnym. W powyższym przykładzie używam |.

Zaletą tej techniki jest to, że jest ona faktycznie niezależna od powłoki.

Możesz także użyć aliasu, pwdaby /bin/pwd | sed "s|$HOME|~|"uzyskać takie zachowanie w innych skryptach, które mogą być używane pwd.

Bichoj
źródło
2
Musisz dołączyć ^kotwicę do wyrażenia regularnego. W przeciwnym razie jest możliwe (choć mało prawdopodobne) zastąpienie segmentu na środku ścieżki.
Sildoreth,
W rzeczywistości wyrażenie regularne powinno wyglądać następująco "s|^/home/user\(/.*\)\?$|~\1|". W przeciwnym razie jest on zgodny ścieżki inni, jeśli ich nazwy są podobne user1, user2, user3i dopasować tylkouser
AVP
3
tilde=\~${PWD#~}

Myślę, że tego właśnie chcesz?

To, co jest fajne w tyldach, to to, że po rozwinięciu jako wzorzec nie trzeba jej cytować. Używanie $HOMEw ten sam sposób bez cudzysłowów dałoby nieprzewidywalne wyniki, ponieważ każdy z jego znaków składowych może być znakami wzorcowymi, a zatem nie zawsze renderuje oczekiwany wynik.

Jednak specyfikacja tyldy zawsze ma miejsce tak, jakby była wynikiem cytowanej interpretacji, więc jej wyniki są przewidywalne. Wydaje się, że jest to prawdą w praktycznie każdej powłoce, którą testowałem zarówno pod względem casewzorców, jak i wzorców parametrów, z godnymi uwagi wyjątkami zarówno ksh93i mkshz jakichkolwiek powodów - z których żaden nie wydaje się honorować cytowanego aspektu tyldy w tym charakterze.

Kolejną ciekawą rzeczą jest to, że możesz na nowo zdefiniować $HOMEobsługę dowolnego katalogu w ten sam sposób. Na przykład:

cd ~
HOME=/some/prefix/I/would/like/to/trim 
#or, perhaps more usefully, some scripted means of arriving at same
tilde=\~${OLDPWD#~}
HOME=$PWD

Oto inny przykład:

set 1 2 3 4 5 \~
cd ~; cd -; HOME= IFS=/
for d do shift
      HOME=${*#~/}/$d
      set ~ "$d" $HOME
done; cd -; HOME=$PWD
printf %s\\n "$@"
5/4/3/2/1/2/3/4/5/~/1/2/3/4/5/~
~
5
4
3
2
1
2
3
4
5
~
1
2
3
4
5
~
mikeserv
źródło
1
To naprawdę interesujące podejście. Ale zakłada, że $PWDjest poniżej $HOME. Możesz użyć tego samego pomysłu w połączeniu z podstawieniem wzorca, aby uczynić go bardziej ogólnym. Jak się czuje ${PWD/#~/\~}?
Mikel
1
Właściwie odpowiedź Nykakina jest w zasadzie taka.
Mikel
0

Możesz spróbować wymienić niechcianą część na sed:

pwd | sed 's,^/data/users/me,~,'

lub nawet lepiej:

pwd | sed "s,^$HOME,~,"
użytkownik1403360
źródło
1
Musisz użyć ^zakotwiczenia, aby zapewnić zastąpienie tylko dopasowań na początku ścieżki do katalogu. Ponadto nie musisz go używać, gponieważ polecenie powinno zastępować co najwyżej 1 wystąpienie.
Sildoreth,
Dziękuję Ci. Nadal się tego uczę, a wasze komentarze są bardzo pomocne.
user1403360,
Problematyczne, jeśli mój katalog osobisty jest, /home/alicea mój bieżący katalog to /home/aliceinchains. Ale jeśli tylko raz chcę skorzystać z tej funkcji, kiedy wiem, że jestem moim katalogiem domowym lub jednym z jego podkatalogów, powinien on działać.
Mihai Danila