Pokaż tylko bieżący i nadrzędny katalog w monicie bash

16

Jestem nowy w bash i chciałbym, aby mój monit pokazał coś, co w tcsh było trywialne, ale po dobrej wyszukiwarce google nadal nie mogę tego zrobić.

Chciałbym, aby mój monit zawierał tylko katalogi bieżący i nadrzędny w następujący sposób:

/parent/currentdir $

W tcsh osiąga się to poprzez:

set prompt = "%C2 %"

Jednak w bash jak dotąd odkryłem tylko, że muszę parsować pwd, aby uzyskać ten sam wynik.

Czy nie ma prostszego sposobu, na przykład:

export PS1="$(some_command) $" 
twalbaum
źródło
2
Teoretycznie PS1='\w \$'; PROMPT_DIRTRIM=2powinien dać ci odpowiednik bash, ale to nie działa poprawnie w moim systemie.
Mikel
W ogóle nie działa na moim: GNU bash, wersja 3.2.57 (1) -release (x86_64-apple-darwin14).
twalbaum,
PROMPT_DIRTRIMzostał wprowadzony w Bash 4 . Właśnie przetestowałem na Ubuntu 16.04 pod WSL i działało świetnie!
Mike Branski,

Odpowiedzi:

18

Funkcje szybkiego sterowania Bash są raczej statyczne. Jeśli chcesz mieć większą kontrolę, możesz dołączyć zmienne do swojego monitu; upewnij się, że nie wyłączyłeś tej promptvarsopcji .

PS1='${PWD#"${PWD%/*/*}/"} \$ '

Zwróć uwagę na pojedyncze cudzysłowy: rozwinięcie zmiennej musi nastąpić w momencie wyświetlenia monitu, a nie w momencie PS1definiowania zmiennej.

Jeśli chcesz mieć większą kontrolę nad tym, co jest wyświetlane, możesz użyć zastępowania poleceń. Na przykład powyższy fragment ~kodu traci skrót do katalogu domowego.

PS1='$(case $PWD in
        $HOME) HPWD="~";;
        $HOME/*/*) HPWD="${PWD#"${PWD%/*/*}/"}";;
        $HOME/*) HPWD="~/${PWD##*/}";;
        /*/*/*) HPWD="${PWD#"${PWD%/*/*}/"}";;
        *) HPWD="$PWD";;
      esac; printf %s "$HPWD") \$ '

Ten kod jest raczej kłopotliwy, więc zamiast wtykać go w PS1zmienną, możesz użyć tej PROMPT_COMMANDzmiennej do uruchomienia kodu, aby ustawić, HPWDa następnie użyć go w wierszu polecenia.

PROMPT_COMMAND='case $PWD in
        $HOME) HPWD="~";;
        $HOME/*/*) HPWD="${PWD#"${PWD%/*/*}/"}";;
        $HOME/*) HPWD="~/${PWD##*/}";;
        /*/*/*) HPWD="${PWD#"${PWD%/*/*}/"}";;
        *) HPWD="$PWD";;
      esac'
PS1='$HPWD \$'

Ponieważ skrócony monit zmienił się tylko przy zmianie katalogu, nie trzeba go ponownie obliczać za każdym razem, gdy wyświetlany jest monit. Bash nie zapewnia przechwytywania, które działa na bieżącej zmianie katalogu, ale możesz to zasymulować, zastępując cdi jego kuzynów.

cd () { builtin cd "$@" && chpwd; }
pushd () { builtin pushd "$@" && chpwd; }
popd () { builtin popd "$@" && chpwd; }
chpwd () {
  case $PWD in
    $HOME) HPWD="~";;
    $HOME/*/*) HPWD="${PWD#"${PWD%/*/*}/"}";;
    $HOME/*) HPWD="~/${PWD##*/}";;
    /*/*/*) HPWD="${PWD#"${PWD%/*/*}/"}";;
    *) HPWD="$PWD";;
  esac
}
PS1='$HPWD \$'

Zauważ, że nie musisz i nie powinieneś eksportować PS1, ponieważ jest to ustawienie powłoki, a nie zmienna środowiskowa. PS1Ustawienie bash nie byłoby zrozumiałe dla innych powłok.

PS Jeśli chcesz miłej interaktywnej powłoki, przełącz się na zsh , gdzie wszystkie z nich (szybkie %rozszerzenia w dużej mierze obejmujące tcsh chpwditp.) Są natywnymi funkcjami.

PS1='%2~ %# '
Gilles „SO- przestań być zły”
źródło
2
To powinna być zaakceptowana i najbardziej pozytywna odpowiedź.
LarsH
3

Składnia uzyskiwania katalogów nadrzędnych i bieżących pochodzi z odpowiedzi Munai .

Jednak, jak zauważył Gilles, ten kod pokazuje tylko bieżący katalog w chwili .bashrczaładowania, ale nie zmieni się podczas nawigacji systemu do innych folderów.

Umieszczenie tego w .bashrcpliku powoduje, że monit zostanie automatycznie zaktualizowany do bieżącego katalogu:

prompt_command () {
    PS1='$(basename $(dirname "$PWD"))/$(basename "$PWD") $ '
}
PROMPT_COMMAND=prompt_command
twalbaum
źródło
1
Czy definiowanie prompt_command()powinno samo w sobie coś zrobić? To nie dla mnie. Czy miałeś na myśli użycie również prompt_command()w redefinicjach cd& co, tak jak zrobił to Gilles? A może miałeś na myśli PROMPT_COMMAND='...'?
LarsH,
2
Również to polecenie kończy się niepowodzeniem, gdy $PWDzawiera spację.
LarsH
1
Dziękuję, że wróciłeś do tego. Przywołano wartości PWD $, aby uwzględnić spacje i dołączono ostateczne polecenie. Moje obecne pytanie jest bardziej skomplikowane, dlatego potrzeba definicji podpowiedzi. W przeciwnym razie PS1 = ... działa na nim.
twalbaum
Jakieś pomysły na oczyszczenie wyjścia podczas nawigacji /? Jak napisano, dostajesz/// $
ezrock
0

Wiersz zachęty można łatwo zmienić bash, edytując zmienną powłoki PS1. Oznacza Monit 1. Ciągu. Więcej informacji tutaj .

Na razie odpal swój bashpocisk.

vi ~/.bashrc

Dołącz definicję PS1 do pliku

`export PS1="$(basename $(dirname $PWD))/$(basename $PWD)"`

Więcej samouczków tutaj i tutaj , aby pomóc Ci jeszcze bardziej go ulepszyć.

Munai Das Udasin
źródło
1
Rozumiem, jak zmodyfikować monit. Moje pytanie brzmi: jak uzyskać tylko katalogi bieżący i nadrzędny, a nie całą ścieżkę.
twalbaum
@twalbaum zredagował moją odpowiedź
Munai Das Udasin
miło mi pomóc @twalbaum :)
Munai Das Udasin
1
Spowoduje to ustawienie monitu na bieżący katalog w momencie .bashrcwczytywania. Monit nie zmieni się, jeśli przejdziesz cddo innego katalogu! @twalbaum
Gilles 'SO- przestań być zły'
@Gilles robi to dla mnie.
twalbaum
0

Może być prostszy z „~” dla katalogu domowego.

function PWDN {
  echo "${PWD/#$HOME/~}" | rev | cut -d "/" -f1 -f2 | rev
}
Baskar
źródło
0
export PS1='[\u@\h $(basename $(dirname ${PWD}))/$(basename ${PWD})]\$ '
export PROMPT_COMMAND='echo -ne "\033]0;$(basename $(dirname $PWD))/$(basename ${PWD})\007"'
Marius
źródło