Вопрос Вызов Bash: как иметь инициалы пути к каталогу


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

hamish@host:src$ 

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

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

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


4
2017-08-24 21:34


происхождения


Это отличный вопрос, но это также точный дубликат вопроса (уже ответил) о переполнении стека: stackoverflow.com/questions/1616678/bash-pwd-shortening - Telemachus
На самом деле это не точный дубликат, хотя он похож. Но, просматривая это, я не могу точно видеть, как делать то, что я хочу - это не фиксированная длина, а только инициалы. Я мог бы пойти и разместить ответ здесь, если мне удастся. - Hamish Downer
Справедливо. Я написал ответ ниже, основываясь на этой теме. - Telemachus
Это также дубликат вот этот, - Dennis Williamson
@Telemachus - полезно ссылаться на решение с другого сайта, но нет причин, чтобы вопрос не мог существовать на обоих сайтах, если он по теме на обоих. Этот вопрос по теме на суперпользователе, на него можно и нужно ответить. - Gnoupi


ответы:


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

  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
2017-08-24 22:13



Я не знаю perl, поэтому не могу судить об общем решении, но я думаю, вам придется отредактировать его, чтобы использовать PROMPT_COMMAND как в моем решении, иначе PS1 будет установлен при запуске bash и не изменится при изменении каталога. - Hamish Downer
@Hamish Нет, это неправильно. Это изменяется, поскольку вы cd, Я использую его сейчас. (И это не Perl. Это связано с тем, как работает PS1. У вас может быть динамическая информация в функции через \$(function), - Telemachus
@Hamish Но вы помогли мне увидеть, что мне нужны двойные кавычки, а не отдельные, как я изначально писал. Приглашение, которое я тестирую здесь, включает в себя цветовые экраны и является более сложным, и я случайно упростил его, используя одинарные кавычки. Сожалею. - Telemachus
ах интересно, мне, очевидно, нужно немного узнать о bash ... - Hamish Downer


Мне нравится подход 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"

3
2017-08-03 17:01



Не могли бы вы объяснить, как функция не жалуется на строку: RESIDUAL=${PWD#$HOME}  даже синтаксический ярлык говорит, что он напуган с # комментарием - stagl
Честно говоря @stagl, прошло много лет с тех пор, как я использовал это приглашение. Я не очень много помню, почему это работает. : / - leff
Добавление. Просто нашел это, исследуя что-то еще. gnu.org/software/bash/manual/html_node/...  «Слово расширяется, чтобы создать шаблон так же, как при расширении имени файла (см. Расширение имени файла). Если шаблон соответствует началу расширенного значения параметра, то результатом расширения является расширенное значение параметра с кратчайшим шаблоном соответствия (случай «#») » - leff


Я переписал это недавно, основываясь на другом сценарии, который я написал много лет назад - этот оптимизирован для максимально возможного использования внутри 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
}

EDIT: исправлена ​​ошибка с абсолютной длиной строки


2
2017-08-25 02:27





PROMPT_DIRTRIM=3

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


2
2018-04-16 14:28





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

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

1
2017-08-24 22:29



Я пробовал это, но, к сожалению, он устанавливает значение PS1один раз, когда вы начинаете bash и после этого не будете обновлять его. Таким образом, вы измените каталог, и ваше приглашение не изменится - я совершил эту ошибку, а затем играл, и мне пришлось почесать голову, чтобы разобраться. См. Мой (отредактированный) ответ для этого PROMPT_COMMAND - Hamish Downer
Нет, он работает для меня, он меняется каждый раз. - cYrus
А также echo $PS1 дает: \ u @ \ h: 'pwd | sed -e "s / \ / (.) [^ \ /] \ + / \ / \ 1 / g" '\ $, поэтому его не сложно закодировать в переменную (я не знаю, как переопределить эту разметку, просто замените 'на `). - cYrus
О, ОК. Я еще прочту, спасибо за объяснение. - Hamish Downer


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

# 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 устанавливается в другом месте, вам нужно будет добавить вышеприведенную команду в конец этого, которому предшествует ;, Итак, для общего примера установки названия xterm вы в конечном итоге получите

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

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


1
2017-08-24 22:38





Другая версия @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}
}

1
2017-09-13 20:05





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

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, ничего не показывать.

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


0
2018-05-26 13:18