Сбой командной строки при использовании дерева каталогов /имени файла

В системе с Ubuntu 14.04 и bash у меня есть PS1, заканчивающийся следующим содержимым:

\[email protected]\h:\w\$

, чтобы приглашение отображалось как

[email protected]:/home/mydirectory$

Иногда, однако, текущий каталог имеет длинное имя или находится внутри каталогов с длинными именами, поэтому приглашение выглядит как

[email protected]:/home/mydirectory1/second_directory_with_a_too_long_name/my_actual_directory_with_another_long_name$

Это заполнит строку в терминале, и курсор перейдет к другой строке, что раздражает.

Я хотел бы вместо этого получить что-то вроде

[email protected]:/home/mydirectory1/...another_long_name$

Есть ли способ определить переменную PS1 для «обертывания» и «компактного» имени каталога, чтобы никогда не превышать определенный количество символов, получение более короткого приглашения?

16 голосов | спросил BowPark 28 FebruaryEurope/MoscowbSun, 28 Feb 2016 14:02:43 +0300000000pmSun, 28 Feb 2016 14:02:43 +030016 2016, 14:02:43

7 ответов


16

Прежде всего, вы можете просто изменить \w с помощью \W. Таким образом, печатается только имя текущего каталога, а не весь его путь:

[email protected]:/home/mydirectory1/second_directory_with_a_too_long_name/my_actual_directory_with_another_long_name $ PS1="\[email protected]\h:\W \$ "
[email protected]:my_actual_directory_with_another_long_name $ 

Этого может быть недостаточно, если имя каталога слишком длинное. В этом случае для этого можно использовать переменную PROMPT_COMMAND. Это специальная переменная bash, значение которой выполняется как команда перед каждым приглашением. Таким образом, если вы установите это для функции, которая задает нужную подсказку в зависимости от длины пути вашего текущего каталога, вы можете получить эффект, который вам нужен. Например, добавьте эти строки в свой ~/.bashrc:

get_PS1(){
        limit=${1:-20}
        if [[ "${#PWD}" -gt "$limit" ]]; then
                ## Take the first 5 characters of the path
                left="${PWD:0:5}"
                ## ${#PWD} is the length of $PWD. Get the last $limit
                ##  characters of $PWD.
                right="${PWD:$((${#PWD}-$limit)):${#PWD}}"
                PS1="\[\033[01;33m\]\[email protected]\h\[\033[01;34m\] ${left}...${right} \$\[\033[00m\] "
        else
                PS1="\[\033[01;33m\]\[email protected]\h\[\033[01;34m\] \w \$\[\033[00m\] "
        fi


}
PROMPT_COMMAND=get_PS1

Эффект выглядит следующим образом:

[email protected] ~ $ cd /home/mydirectory1/second_directory_with_a_too_long_name/my_actual_directory_with_another_long_name
[email protected] /home...th_another_long_name $ 
ответил terdon 28 FebruaryEurope/MoscowbSun, 28 Feb 2016 15:00:26 +0300000000pmSun, 28 Feb 2016 15:00:26 +030016 2016, 15:00:26
10

Добавление в возврат символа является моим основным решением для этого

Итак, моя подсказка (которая имеет и другие вещи, делая ее еще дольше) выглядит следующим образом:

 введите описание изображения здесь>> </a> </p>

<p> Вы заметите, что $ возвращается в новую строку </p>

<p> Я достигаю этого с помощью </p>

<pre><code>---- +: = 0 = + ----</code></pre>

<p> Обратите внимание, что, хотя на отдельной строке, очень длинные деревья каталогов, такие как </p>

<p> <code>---- +: = 1 =: + ----</code> сокращены до </p>

<pre><code>---- +: = 2 = + ----</code></pre>

<p> то есть. «верхние 3 каталога /_ /дно двух каталогов», которые, как правило, меня волнует </p>

<p> Это позволит убедиться, что строка никогда не становится слишком длинной из-за длины дерева каталогов. Если вы всегда хотите, чтобы полное дерево каталогов только изменилось LOCATION, то есть </p>

<pre><code>---- +: = 3 = + ----</code></pre></body></html>

ответил Michael Durrant 28 FebruaryEurope/MoscowbSun, 28 Feb 2016 19:43:45 +0300000000pmSun, 28 Feb 2016 19:43:45 +030016 2016, 19:43:45
3

Создано ~ /.bash_prompt:

maxlen=36
# set leftlen to zero for printing just the right part of the path
leftlen=19
shortened="..."
# Default PWD
nPWD=${PWD}
if [ ${#nPWD} -gt $maxlen ]; then
  offset=$(( ${#nPWD} - $maxlen + $leftlen ))
  nPWD="${nPWD:0:$leftlen}${shortened}${nPWD:$offset:$maxlen}"
else
  nPWD='\w'
fi
echo "\[email protected]\h:$nPWD\$ "

Добавлен в мой файл ~ /.bash_profile:

function prompt_command {
  export PS1=$(~/.bash_prompt)
}
export PROMPT_COMMAND=prompt_command

Выход:

[email protected]:/home/mydirectory1/...another_long_name$
ответил hellcode 28 FebruaryEurope/MoscowbSun, 28 Feb 2016 15:54:53 +0300000000pmSun, 28 Feb 2016 15:54:53 +030016 2016, 15:54:53
1

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

[email protected]:~
$ echo $PS1
\[email protected]\h:\w\n\$
[email protected]:~
$ 
ответил Murphy 28 FebruaryEurope/MoscowbSun, 28 Feb 2016 14:58:17 +0300000000pmSun, 28 Feb 2016 14:58:17 +030016 2016, 14:58:17
1

Я использую это, он переносит на несколько строк и отступов на длину [email protected], поэтому он принимает текущий PS1 эффективно '\[email protected]\h:\w$'. Он не усекает путь и адаптируется к текущей ширине терминала. Он разделяет путь только на /, поэтому он не элегантно разбирается с действительно длинными каталогами (но он сохраняет пробелы для выбора /копирования ). Это гарантирует, что у вас всегда есть доступное для ввода 20 символов.

readonly _PS1="${PS1}" 2>/dev/null

function myprompt()
{
    local IFS
    local nn nb pbits xpwd="" ww=60 len=0 pp='\\w\$ '
    local indent uh="${LOGNAME}@${HOSTNAME//.*/}"

    test -n "$COLUMNS" && let ww=$COLUMNS-20  # may be unset at startup

    PS1="${_PS1}"
    if [ ${#PWD} -ge $ww ]; then
        printf -v indent "%${#uh}s%s" " " "> "  # indent strlen([email protected])

        IFS=/ pbits=( $PWD ); unset IFS
        nb=${#pbits[*]}
        for ((nn=1; nn<nb; nn++)) {
            if [ $(( $len + 1 + ${#pbits[$nn]} )) -gt $ww ]; then
                xpwd="${xpwd}/...\n${indent}..."
                len=0
            fi
            xpwd="${xpwd}/${pbits[$nn]}"
            let len=len+1+${#pbits[$nn]}
        }
        # add another newline+indent if the input space is too tight
        if (( ( ${#uh} + len ) > ww )); then
            printf -v xpwd "${xpwd}\n%${#uh}s" " " 
        fi 
        PS1="${PS1/$pp/$xpwd}$ "    
    fi
}
PROMPT_COMMAND=myprompt

Это работает, беря магический \w (соответствует только \w$) из PS1 и заменив его на $PWD, затем обертывая его как обычную строку символов. Он пересчитывает PS1 каждый раз из исходного значения, которое сохраняется в _PS1, это означает, что также сохраняются «невидимые» escape-последовательности, моя полная исходная строка приглашения для xterm и полужирное приглашение:

PS1="\[\033]0;\[email protected]\h:\w\007\]\[$(tput bold)\]\[email protected]\h\[$(tput sgr0)\]:\w$ "

И конечный результат в терминале 80 столбцов:

[email protected]:~$ cd /usr/src/linux/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace
[email protected]:/usr/src/linux/tools/perf/scripts/perl/Perf-Trace-Util/lib/...
               > .../Perf/Trace$ _

Это работает с bash-3.2 в качестве printf -v var. Из-за различных сложностей ему потребуется некоторая корректировка для других вариантов PS1

(Путь в строке заголовка xterm не является ни обернутым, ни сокращенным, что может быть сделано путем включения одного из других ответов здесь в указанную выше функцию.)

ответил mr.spuratic 29 FebruaryEurope/MoscowbMon, 29 Feb 2016 14:29:07 +0300000000pmMon, 29 Feb 2016 14:29:07 +030016 2016, 14:29:07
0

В качестве альтернативы, в моем .zshrc я сокращаю первую букву каждого каталога, если ширина пикселя превышает определенную ширину:

[email protected]:/home/mydirectory1/second_directory
[email protected]:/home/mydirectory1/second_directory/my_actual_directory

становится:

[email protected]:/h/mydirectory1/second_directory
[email protected]:/h/m/s/my_actual_directory

Вот функция zsh:

     # get the path
     t=`print -P "%m:%~"`;
     t=`echo $t | sed -r 's/([^:])[^:]*([0-9][0-9]):|([^:])[^:]*([^:]):/\1\2\3\4:/'`;
     oldlen=-1;

     # create 4 buckets of letters by their widths
     t1="${t//[^ijlIFT]}";
     t2="${t//[ijlIFTGoQMmWABEKPSVXYCDHNRUw]}";
     t3="${t//[^ABEKPSVXYCDHNRUw]}";
     t4="${t//[^GoQMmW]}";

     # keep abbreviating parent directories in the path until under 456 pixels
     while (( ( ( ${#t1} * 150 ) + ( ${#t2} * 178 ) + ( ${#t3} * 190 ) + ( ${#t4} * 201 ) ) > 4560 && ${#t}!=oldlen)) {
       oldlen=${#t};
       t=`echo $t | sed 's/\/\(.\)[^\/][^\/]*\//\/\1\//'`;
       t1="${t//[^ijlIFT]}";
       t2="${t//[ijlIFTGoQMmWABEKPSVXYCDHNRUw]}";
       t3="${t//[^ABEKPSVXYCDHNRUw]}";
       t4="${t//[^GoQMmW]}";
     };

     PS1=$t

Я действительно использую это, чтобы обновить заголовок терминала, чтобы с помощью нескольких вкладок я мог сохранить прямую, какая вкладка есть. Полный .zshrc для этого - здесь .

Это очень удобно, так как он поддерживает контекст, а в zsh позволяет быстро выполнить вкладку с полным каталогом в том же формате. (например, ввод cd /h/m/s/<tab> будет автозаполнен до cd /home/mydirectory1/second_directory )

ответил Richard 28 FebruaryEurope/MoscowbSun, 28 Feb 2016 22:22:35 +0300000000pmSun, 28 Feb 2016 22:22:35 +030016 2016, 22:22:35
0

Попробуйте использовать этот скрипт Python . Он отсекает отдельные разделы имени пути, точно так же, как вы хотели в своем вопросе. Он также использует эллипсис Unicode, который занимает только один столбец вместо трех.

Пример вывода для вашего пути (при заданном значении 30 символов):

/home/mydir…/second…/my_actua…

Стоит отметить, что это решение правильно обрабатывает Unicode в именах каталогов, используя wcswidth . ${#PWD}, который использовали другие ответы, неправильно ошибочно оценивает визуальную ширину любого пути, содержащего символы UTF-8.

ответил Functino 28 FebruaryEurope/MoscowbSun, 28 Feb 2016 17:57:20 +0300000000pmSun, 28 Feb 2016 17:57:20 +030016 2016, 17:57:20

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132