Abreviando um nome de diretório relativo a um diretório de base

1

No Bash, o diretório ~ tem um status especial, pois se o diretório atual residir em ~ , ele será automaticamente reduzido. Ou seja, dirs +0 e o átomo de substituição \w em PS1 mostra

$ dirs +0
~/test/directory

Em vez de /home/myname/test/directory .

É possível conceder a outro diretório esse status especial? Costumo trabalhar em uma árvore de fontes em que o nível superior é $DEV ou $SRC e gostaria de mostrar o diretório atual em PS1 as

$SRC/current/working/directory

em vez de (por exemplo)

~/projects/devel/source/current/working/directory
    
por Henricus V. 28.08.2018 / 17:06

1 resposta

3

Se $ PS1 contiver expansões de variáveis literais, elas serão expandidas preguiçosamente toda vez que o prompt for exibido. Portanto, o método direto, de apenas uma substituição, é usar ${var/#search/replacement} para trocar um prefixo por outro:

PS1='\u@\h ${PWD/#"${SRC:-xxx}"/"\$SRC"} \$ '

Observe como a atribuição usa aspas simples, portanto, a expansão ${PWD...} é incluída na íntegra, não expandida no momento da atribuição. (A expansão preguiçosa do PS1 é feita por padrão no bash, mas também é possível no zsh se você souber qual opção ativar. Eu não sei.)

O uso de ${SRC:-xxx} em vez de apenas $SRC é uma proteção contra o $ SRC sendo vazio ou não definido, caso em que você obteria o prefixo em todos os lugares, em vez de em nenhum lugar.

O método um pouco mais complexo é chamar uma função personalizada e deixá-la gerar a saída desejada:

show_abbrevd_path() {
    # longest prefix should be first
    case $PWD in
        "$SRC/"*)  echo "${PWD/#"$SRC/"/"\$SRC/"}";;
        "$HOME/"*) echo "${PWD/#"$HOME/"/"~/"}";;
        *)         echo "$PWD";;
    esac
}

PS1='\u@\h $(show_abbrevd_path) \$ '

(Não do lado: As aspas em "${PWD/#"$SRC/"/"\$SRC/"}" são realmente aninhadas e não fechadas / reabertas. $ {…} é mágica assim, apesar de o marcador de sintaxe da SU pensar no contrário.)

É claro que não precisa ser uma função - você também pode usar $(pwd | sed ...) ou $(perl ...) ou $(~/bin/fancypwd) - mas quanto mais processos você criar, mais tempo levará para exibir seu prompt e shell parece mais lento como resultado.

Na mesma nota, você poderia obter o mesmo efeito com subprocessos zero chamando a função via $ PROMPT_COMMAND e recuperando seu estado global, evitando assim o subshell $ (…):

make_abbrevd_path() {
    case $PWD in
        "$SRC/"*)  xpwd="${PWD/#"$SRC/"/"\$SRC/"}";;
        "$HOME/"*) xpwd="${PWD/#"$HOME/"/"~/"}";;
        *)         xpwd="$PWD";;
    esac
}

PROMPT_COMMAND='make_abbrevd_path'

PS1='\u@\h $xpwd \$ '
    
por 28.08.2018 / 17:54