4

У меня обычно есть только имя текущего каталога в моем приглашении bash (PS1='\u@\h:\W$ '), поэтому, если я нахожусь в ~/projects/superapp/src/ я получаю:

hamish@host:src$ 

Однако я хотел бы иметь указание полного пути без полного пути. Я видел скриншоты, где люди будут иметь

hamish@host:~/p/s/src$ 

если в примере каталога выше. Так какое значение PS1 даст это? Или, если это не удалось, какой скрипт мне нужен в моем .bashrc для его создания?

8 ответов8

3

Мне нравится подход meowsqueak, пытающийся остаться в bash для производительности. Но я хотел, чтобы мой путь сокращал длинные имена каталогов до одного символа.

me@comp:~ $ cd my/path/haslongnames/
me@comp:~my/p/h $

Это основано на решении meowsqueak. Он может выдержать некоторые улучшения / дополнительные функции, но он решает основную проблему без запуска sed.

Это в исполняемом файле, например ~/bin/ps1

# set this to whatever you want:
MAX_PWD_LENGTH=30
function shorten_pwd
{
    # This function ensures that the PWD string does not exceed $MAX_PWD_LENGTH characters
    PWD=$(pwd)

    # determine part of path within HOME, or entire path if not in HOME
    RESIDUAL=${PWD#$HOME}

    # compare RESIDUAL with PWD to determine whether we are in HOME or not
    if [ X"$RESIDUAL" != X"$PWD" ]
    then
        PREFIX="~"
    fi

    # check if residual path needs truncating to keep total length below MAX_PWD_LENGTH
    NORMAL=${PREFIX}${RESIDUAL}
    if [ ${#NORMAL} -ge $(($MAX_PWD_LENGTH)) ]
    then
        newPWD=${PREFIX}
        OIFS=$IFS
        IFS='/'
        bits=$RESIDUAL
        for x in $bits
        do
            if [ ${#x} -ge 3 ]
            then
                NEXT="/${x:0:1}"
            else
                NEXT="$x"
            fi
            newPWD="$newPWD$NEXT"
        done

        IFS=$OIFS
    else
        newPWD=${PREFIX}${RESIDUAL}
    fi

    # return to caller
    echo $newPWD
}
export PS1="\u@\h:$(shorten_pwd) $ "

В моем .bash_profile у меня тогда есть

PROMPT_COMMAND="source $HOME/bin/ps1"
2

Хорошо, мне стало любопытно, так что вот одно решение:

  1. Во-первых, создайте функцию, используя небольшую настройку ответа Уильяма Перселла на вопрос SO, на который я ссылаюсь в своем комментарии выше.
  2. Затем поместите это в свой $ PS1 как \$(function_name) в соответствующем месте.

В качестве примера:

short_pwd() {
    cwd=$(pwd | perl -F/ -ane 'print join( "/", map { $i++ < @F - 1 ?  substr $_,0,1 : $_ } @F)')
    echo -n $cwd
}
# later in your .bashrc
PS1="\u \$(short_pwd) \$ "

Я надеюсь, что кто-то более опытный в написании Bash-скриптов, чем я, может предложить способы очистки функции, но это должно дать вам некоторое представление о том, как использовать вывод другой команды (или функции Bash) в приглашении. Смотрите также здесь: http://www.linux.org/docs/ldp/howto/Bash-Prompt-HOWTO/x279.html

Основываясь на вашем комментарии, я снова посмотрел и понял, что мое решение должно быть в двойных кавычках. Если вы поставите в кавычки такую функцию, она вообще не будет работать.

2

Я переписал это недавно, основываясь на другом сценарии, который написал несколько лет назад - этот оптимизирован для максимально возможного запуска внутри bash, чтобы избежать дорогостоящих форков. Это было почти в 8 раз быстрее, чем моя старая функция, которая использовала awk/sed.

Это дает хорошие результаты. Он сохраняет часть приглашения pwd не более MAX_PWD_LENGTH символов, и, если вы находитесь в подкаталоге $ HOME, это также ясно дает понять:

Примеры:

pc770-ubu:~ $ cd ~/a/b/c
pc770-ubu:~/a/b/c $ cd d/e/f
pc770-ubu:~/a/b/c/d/e/f $ cd g
pc770-ubu:~/a/b/c/d/e/f/g $ cd h
pc770-ubu:~/a/b/c/d/e/f/g/h $ cd i
pc770-ubu:~/a/b/c/d/e/f/g/h/i $ cd j
pc770-ubu:~/a/b/c/d/e/f/g/h/i/j $ cd k
pc770-ubu:~/a/b/c/d/e/f/g/h/i/j/k $ cd l
pc770-ubu:~../c/d/e/f/g/h/i/j/k/l $ cd m
pc770-ubu:~../d/e/f/g/h/i/j/k/l/m $ cd n
pc770-ubu:~../e/f/g/h/i/j/k/l/m/n $ cd o
pc770-ubu:~../f/g/h/i/j/k/l/m/n/o $ cd /tmp/a/b/c/d/e/f
pc770-ubu:/tmp/a/b/c/d/e/f $ cd g
pc770-ubu:/tmp/a/b/c/d/e/f/g $ cd h
pc770-ubu:/tmp/a/b/c/d/e/f/g/h $ cd i
pc770-ubu:/tmp/a/b/c/d/e/f/g/h/i $ cd j
pc770-ubu:/../a/b/c/d/e/f/g/h/i/j $ cd k
pc770-ubu:/../b/c/d/e/f/g/h/i/j/k $ cd l
pc770-ubu:/../c/d/e/f/g/h/i/j/k/l $ cd m
pc770-ubu:/../d/e/f/g/h/i/j/k/l/m $ cd
pc770-ubu:~ $ 

Функция bash (вызывайте ее при создании переменной PS1):

# set this to whatever you want:
MAX_PWD_LENGTH=20

function shorten_pwd
{
    # This function ensures that the PWD string does not exceed $MAX_PWD_LENGTH characters
    PWD=$(pwd)

    # if truncated, replace truncated part with this string:
    REPLACE="/.."

    # determine part of path within HOME, or entire path if not in HOME
    RESIDUAL=${PWD#$HOME}

    # compare RESIDUAL with PWD to determine whether we are in HOME or not
    if [ X"$RESIDUAL" != X"$PWD" ]
    then
        PREFIX="~"
    fi

    # check if residual path needs truncating to keep total length below MAX_PWD_LENGTH
    # compensate for replacement string.
    TRUNC_LENGTH=$(($MAX_PWD_LENGTH - ${#PREFIX} - ${#REPLACE} - 1))
    NORMAL=${PREFIX}${RESIDUAL}
    if [ ${#NORMAL} -ge $(($MAX_PWD_LENGTH)) ]
    then
        newPWD=${PREFIX}${REPLACE}${RESIDUAL:((${#RESIDUAL} - $TRUNC_LENGTH)):$TRUNC_LENGTH}
    else
        newPWD=${PREFIX}${RESIDUAL}
    fi

    # return to caller
    echo $newPWD
}

РЕДАКТИРОВАТЬ: исправлена ошибка с абсолютной длиной строки

2
PROMPT_DIRTRIM=3

заставит \w развернуть максимум до трех конечных элементов текущего пути рабочего каталога, при этом предшествующий, если таковой имеется, будет заменен на «...».

1

Просто добавьте это (и отредактируйте как хотите) к вашему .bashrc:

PS1='\u@\h:`pwd | sed -e "s/\/\(.\)[^\/]\+/\/\1/g"`\$ '
1

Тем временем я немного погуглил, и, пройдя несколько поисковых запросов, я наткнулся на эту статью, в которой упоминается, что раковина рыбы делает то, что я хочу, и предоставлен способ сделать это. Я изменил его так, чтобы пользователь и хост также отображались и в итоге получили достаточно краткую информацию:

# abbreviate the dir path
PROMPT_COMMAND='CurDir=`pwd|sed -e "s!$HOME!~!"|sed -re "s!([^/])[^/]+/!\1/!g"`'
PS1="\u@\h:\$CurDir \$ "

По сути, каждый раз, когда приглашение будет отображаться, PROMPT_COMMAND будет устанавливать $CurDir в качестве сокращенного пути к каталогу, который затем используется в $PS1 . Имейте в виду, что если PROMPT_COMMAND установлен в другом месте, вам нужно будет добавить вышеупомянутую команду в конец той, которой предшествует a ; , Так что для общего примера установки заголовка xterm вы бы в конечном итоге

PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME}: ${PWD/$HOME/~}\007"; CurDir=`pwd|sed -e "s!$HOME!~!"|sed -re "s!([^/])[^/]+/!\1/!g"`'

Некоторые другие возможные способы сокращения пути могут быть найдены:

1

Другая версия @Telemachus short_pwd(), без требования perl.

short_pwd() {
cwd=$(pwd)

if [ $cwd == $HOME ]; then echo -n "~"; return; fi 
if [ $cwd == "/" ]; then echo -n "/"; fi 

for l in $(echo $cwd | tr "/" "\n"); do 
    echo -n "/"
    echo -n ${l:0:1}
done
echo -n ${l:1}
}
0

Попробуй это:

PS1='$(pp="$PWD/" q=${pp/#"$HOME/"/} p=${q%?};((${#p}>19))&&echo "${p::9}…${p:(-9)}"||echo "$p") \$'

Трансформируется

~/.vim/bundle/ack.vim/plugin

в

.vim/bund…im/plugin

transfrom

/usr/share/doc/xorg-x11-font-utils-7.5/

в

/usr/shar…utils-7.5

И когда $PWD совпадает с $HOME , ничего не показывать.

Бонус: вы можете изменить количество длины, чтобы соответствовать вам нужно.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .