Mostrar solo el directorio actual y el primario en bash prompt

16

Soy nuevo en bash y me gustaría que mi mensaje muestre algo que en tcsh fue trivial, pero después de una buena búsqueda en Google todavía no puedo hacer.

Me gustaría que mi mensaje incluya solo los directorios actuales y principales como este:

/parent/currentdir $

En tcsh esto se logra mediante:

set prompt = "%C2 %"

Sin embargo, en bash hasta ahora solo he encontrado que tengo que analizar pwd para obtener la misma salida.

¿No hay una manera más simple, como hacer:

export PS1="$(some_command) $" 
twalbaum
fuente
2
En teoría, PS1='\w \$'; PROMPT_DIRTRIM=2debería darte el equivalente de bash, pero eso no funciona correctamente en mi sistema.
Mikel
No funciona en absoluto en el mío: GNU bash, versión 3.2.57 (1) -release (x86_64-apple-darwin14).
twalbaum
PROMPT_DIRTRIMfue introducido en Bash 4 . ¡Acabo de probar en Ubuntu 16.04 con WSL y funcionó muy bien!
Mike Branski

Respuestas:

18

Las características de control rápido de Bash son bastante estáticas. Si desea más control, puede incluir variables en su solicitud; asegúrese de no haber desactivado la promptvarsopción .

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

Tenga en cuenta las comillas simples: las expansiones de las variables deben ocurrir en el momento en que se muestra la solicitud, no en el momento en PS1que se define la variable.

Si desea tener más control sobre lo que se muestra, puede usar sustituciones de comandos. Por ejemplo, el fragmento anterior pierde la ~abreviatura del directorio de inicio.

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

Este código es bastante engorroso, por lo que en lugar de pegarlo en la PS1variable, puede usar la PROMPT_COMMANDvariable para ejecutar el código para configurarlo HPWDy luego usarlo en su solicitud.

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

Dado que la solicitud abreviada solo cambió en un cambio de directorio, no necesita volver a calcularla cada vez que se muestra una solicitud. Bash no proporciona un enlace que se ejecute en un cambio de directorio actual, pero puede simularlo anulando cdy sus primos.

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

Tenga en cuenta que no necesita y no debe exportar PS1, ya que es una configuración de shell, no una variable de entorno. Una PS1configuración de bash no sería entendida por otros proyectiles.

PD: si desea una buena experiencia de shell interactivo, cambie a zsh , donde todas estas ( %expansiones rápidas que abarcan en gran medida tcsh chpwd, etc.) son características nativas.

PS1='%2~ %# '
Gilles 'SO- deja de ser malvado'
fuente
2
Esta debería haber sido la respuesta aceptada y más votada.
LarsH
3

La sintaxis para obtener los directorios padre y actual se toma de la respuesta de Munai .

Sin embargo, como señaló Gilles, ese código solo muestra el directorio actual en el momento en que .bashrcse carga, pero no cambiará a medida que navega por el sistema a otras carpetas.

Tener esto en su .bashrcarchivo hace que la solicitud se actualice automáticamente en su directorio actual:

prompt_command () {
    PS1='$(basename $(dirname "$PWD"))/$(basename "$PWD") $ '
}
PROMPT_COMMAND=prompt_command
twalbaum
fuente
1
¿Se prompt_command()supone que definir debe hacer algo por sí solo? No es para mi. ¿Querías usar también prompt_command()en redefiniciones de cd& co, como hizo Gilles? ¿O quisiste decir PROMPT_COMMAND='...'?
LarsH
2
Además, este comando falla cuando $PWDcontiene un espacio.
LarsH
1
Gracias por traerme de vuelta a esto. Citó los $ PWD para permitir espacios e incluyó el comando final. Mi solicitud actual es más compleja que esta, por lo tanto, la necesidad de la definición prompt_command. De lo contrario, PS1 = ... funciona en su encendido.
twalbaum
¿Alguna idea para limpiar la salida al navegar a /? Como está escrito, obtienes/// $
ezrock
0

La cadena de solicitud se puede cambiar fácilmente basheditando la variable de shell PS1. Significa Prompt String 1. Más información aquí .

Por ahora enciende tu bashcaparazón.

vi ~/.bashrc

Agregue la definición de PS1 en el archivo

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

Más tutoriales aquí y aquí , para ayudarlo a ajustarlo aún más.

Munai Das Udasin
fuente
1
Entiendo cómo modificar el aviso. Mi pregunta es cómo obtener solo los directorios actuales y principales, no toda la ruta.
twalbaum
@twalbaum editó mi respuesta
Munai Das Udasin
me alegro de ayudar @twalbaum :)
Munai Das Udasin
1
Esto establece el aviso en el directorio actual en el momento en que .bashrcse carga, ¡el aviso no cambiará si ingresa cden otro directorio! @twalbaum
Gilles 'SO- deja de ser malvado'
@Gilles lo hace por mí.
twalbaum
0

Puede ser más simple con "~" para el directorio de inicio.

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