Показывать только текущий и родительский каталог в приглашении bash

16

Я новичок в bash и хотел бы, чтобы моя подсказка показывала что-то, что в tcsh было тривиально, но после хорошего поиска в Google я все еще не могу это сделать.

Я хотел бы, чтобы мое приглашение включало только текущие и родительские каталоги, как это:

/parent/currentdir $

В tcsh это достигается путем:

set prompt = "%C2 %"

Однако в bash я обнаружил, что мне нужно разобрать pwd для получения того же результата.

Разве нет более простого способа, например:

export PS1="$(some_command) $" 
twalbaum
источник
2
Теоретически, PS1='\w \$'; PROMPT_DIRTRIM=2должен дать вам эквивалент bash, но он не работает должным образом в моей системе.
Микель
Это не работает на моем: GNU bash, версия 3.2.57 (1) -релиз (x86_64-apple-darwin14).
Твальбаум
PROMPT_DIRTRIMбыл введен в Bash 4 . Я только что проверил на Ubuntu 16.04 под WSL, и он работал отлично!
Майк Брански,

Ответы:

18

Функции быстрого управления Bash довольно статичны. Если вы хотите больше контроля, вы можете включить переменные в ваше приглашение; убедитесь, что вы не отключили эту promptvarsопцию .

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

Обратите внимание на одинарные кавычки: раскрытие переменных должно происходить во время отображения приглашения, а не во время определения PS1переменной.

Если вы хотите больше контроля над тем, что отображается, вы можете использовать подстановки команд. Например, приведенный выше фрагмент теряет ~сокращение для домашнего каталога.

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

Этот код довольно громоздок, поэтому вместо того, чтобы вставлять его в PS1переменную, вы можете использовать PROMPT_COMMANDпеременную для запуска кода, чтобы установить HPWDи затем использовать его в своем приглашении.

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

Поскольку сокращенная подсказка изменялась только при смене каталога, вам не нужно пересчитывать ее каждый раз, когда отображается подсказка. Bash не предоставляет ловушку, которая запускается при текущем изменении каталога, но вы можете имитировать его , переопределяя cdи его кузенов.

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 \$'

Обратите внимание, что вам не нужно и не нужно экспортировать PS1, так как это параметр оболочки, а не переменная окружения. PS1Настройка bash не будет понята другими оболочками.

PS Если вы хотите получить приятную интерактивную оболочку, переключитесь на zsh , где все они (быстрые %расширения, в основном включающие tcsh и chpwdт. Д.) Являются встроенными функциями.

PS1='%2~ %# '
Жиль "ТАК - прекрати быть злым"
источник
2
Это должен был быть принятый и наиболее одобренный ответ.
LarsH
3

Синтаксис для получения родительских и текущих каталогов взят из ответа Мунай .

Однако, как отметил Жиль, этот код показывает только текущий каталог, .bashrcзагруженный во время загрузки, но он не изменится, когда вы перейдете в систему к другим папкам.

Наличие этого в вашем .bashrcфайле делает приглашение автоматически обновленным в текущем каталоге:

prompt_command () {
    PS1='$(basename $(dirname "$PWD"))/$(basename "$PWD") $ '
}
PROMPT_COMMAND=prompt_command
twalbaum
источник
1
Определение prompt_command()должно что-то делать само по себе? Это не для меня. Вы хотели также использовать prompt_command()в переопределениях cd& co, как это сделал Жиль? Или ты имел ввиду PROMPT_COMMAND='...'?
LarsH
2
Кроме того, эта команда не выполняется, если $PWDсодержит пробел.
LarsH
1
Спасибо, что вернули меня к этому. Процитировал $ PWD, чтобы учесть пробелы, и включил последнюю команду. Моя текущая подсказка является более сложной, чем эта, поэтому требуется определение prompt_command. В противном случае PS1 = ... работает дальше.
Твальбаум
Любые идеи для очистки вывода при переходе к /? Как написано, вы получаете/// $
ezrock
0

Строка подсказки может быть легко изменена bashпутем редактирования переменной оболочки PS1. Это означает «Строка подсказки 1.» Более подробная информация здесь .

А пока запусти свой bashснаряд.

vi ~/.bashrc

Добавить определение PS1 в файл

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

Больше учебников здесь и здесь , чтобы помочь вам настроить его еще больше.

Мунай Дас Удасин
источник
1
Я понимаю, как изменить подсказку. У меня вопрос, как получить только текущие и родительские каталоги, а не весь путь.
Твальбаум
@twalbaum отредактировал мой ответ
Мунай Дас Удасин
рад помочь @twalbaum :)
Мунай Дас Удасин
1
Это устанавливает приглашение для текущего каталога в момент .bashrcзагрузки, приглашение не изменится, если вы перейдете cdв другой каталог! @twalbaum
Жиль "
@ Жиль, это для меня.
Твальбаум
0

Может быть проще с "~" для домашнего каталога.

function PWDN {
  echo "${PWD/#$HOME/~}" | rev | cut -d "/" -f1 -f2 | rev
}
Baskar
источник
0
export PS1='[\u@\h $(basename $(dirname ${PWD}))/$(basename ${PWD})]\$ '
export PROMPT_COMMAND='echo -ne "\033]0;$(basename $(dirname $PWD))/$(basename ${PWD})\007"'
Marius
источник