Как я могу сократить текущий каталог моей командной строки? - PullRequest
52 голосов
/ 16 апреля 2011

Я использую Ubuntu, и мне надоели такие длинные подсказки в bash, когда я работаю с какой-то глубокой иерархией каталогов.Итак, я хотел бы настроить PS1, чтобы сократить рабочую часть каталога следующим образом:

В настоящее время у меня есть:

pajton@dragon:~/workspace/projects/project1/folder1/test$

и хотелось бы иметь:

pajton@dragon:~/workspace/.../folder1/test$

Усечение произойдет, если len ($ PWD) пройдет заданное пороговое значение.Я хочу всегда сохранять первый компонент пути и по крайней мере один последний компонент пути.Затем, если позволяет пространство, добавьте больше компонентов справа.

Это то, что у меня есть в настоящее время.Это работает, но: 1) не сохраняет первый компонент пути, 2) не учитывает путь резки на границах:

pwd_length=14
pwd_symbol="..."
newPWD="${PWD/#$HOME/~}"

if [ $(echo -n $newPWD | wc -c | tr -d " ") -gt $pwd_length ]
then
   newPWD="...$(echo -n $PWD | sed -e "s/.*\(.\{$pwd_length\}\)/\1/")"
else
   newPWD="$(echo -n $PWD)"
fi

И результат:

pajton@dragon:...sth/folder1/sample$ 

Спасибо зазаранее!

Ответы [ 10 ]

113 голосов
/ 08 декабря 2011

Для людей, которые ищут гораздо более простое решение и не нуждаются в имени первого каталога в пути, Bash имеет встроенную поддержку для этого с помощью переменной PROMPT_DIRTRIM. Из документации :

PROMPT_DIRTRIM

Если установлено значение больше нуля, это значение используется в качестве количества компонентов конечного каталога, которые сохраняются при расширениистрока приглашения \ w и \ W экранируется (см. Печать приглашения).Удаленные символы заменяются многоточием.

Например:

~$ mkdir -p a/b/c/d/e/f
~$ cd a/b/c/d/e/f
~/a/b/c/d/e/f$ export PROMPT_DIRTRIM=2
~/.../e/f$ PROMPT_DIRTRIM=3
~/.../d/e/f$ 

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

ПеревернутыйЭто очень просто.Просто добавьте export PROMPT_DIRTRIM=2 к вашему .bashrc.

45 голосов
/ 16 апреля 2011

Рассмотрим этот сценарий, используя awk вместо sed для вашего случая:

pwd_length=14
pwd_symbol="..."
newPWD="${PWD/#$HOME/~}"
if [ $(echo -n $newPWD | wc -c | tr -d " ") -gt $pwd_length ]
then
   newPWD=$(echo -n $newPWD | awk -F '/' '{
   print $1 "/" $2 "/.../" $(NF-1) "/" $(NF)}')
fi
PS1='${newPWD}$ '

Для вашего примера каталога ~/workspace/projects/project1/folder1/test PS1 выглядит следующим образом: ~/workspace/.../folder1/test

UPDATE

Приведенное выше решение будет устанавливать ваше приглашение, но, как вы отметили в своем комментарии, оно НЕ будет динамически менять PS1 при смене каталога. Итак, вот решение, которое будет динамически устанавливать PS1 при смене каталогов.

Поместите эти 2 строки в ваш файл .bashrc:

export MYPS='$(echo -n "${PWD/#$HOME/~}" | awk -F "/" '"'"'{
if (length($0) > 14) { if (NF>4) print $1 "/" $2 "/.../" $(NF-1) "/" $NF;
else if (NF>3) print $1 "/" $2 "/.../" $NF;
else print $1 "/.../" $NF; }
else print $0;}'"'"')'
PS1='$(eval "echo ${MYPS}")$ '

if (NF > 4 && length($0) > 14) Условие в awk будет применять специальную обработку только в том случае, если ваш текущий каталог имеет глубину более 3 каталогов И если длина $PWD превышает 14 символов, в противном случае PS1 будет сохраняться как $PWD.

Например: если текущий каталог ~/workspace/projects/project1$, то PS1 будет ~/workspace/projects/project1$

Эффект выше в .bashrc будет следующим для вашей PS1:

~$ cd ~/workspace/projects/project1/folder1/test
~/workspace/.../folder1/test$ cd ..
~/workspace/.../project1/folder1$ cd ..
~/workspace/.../project1$ cd ..
~/.../projects$ cd ..
~/workspace$ cd ..
~$

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

9 голосов
/ 06 марта 2013

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

Он свернет путь, если его глубина более 16 символов и 4 уровня. Кроме того, в ... сколько каталогов было свернуто, так что вы получите представление о глубине пути, то есть: ~/usr/..4../path2/path1 означает, что были свернуты 4 уровня.

# define the awk script using heredoc notation for easy modification
MYPSDIR_AWK=$(cat << 'EOF'
BEGIN { FS = OFS = "/" }
{ 
   sub(ENVIRON["HOME"], "~");
   if (length($0) > 16 && NF > 4)
      print $1,$2,".." NF-4 "..",$(NF-1),$NF
   else
      print $0
}
EOF
)

# my replacement for \w prompt expansion
export MYPSDIR='$(echo -n "$PWD" | awk "$MYPSDIR_AWK")'

# the fancy colorized prompt: [0 user@host ~]$
# return code is in green, user@host is in bold/white
export PS1='[\[\033[1;32m\]$?\[\033[0;0m\] \[\033[0;1m\]\u@\h\[\033[0;0m\] $(eval "echo ${MYPSDIR}")]$ '

# set x/ssh window title as well
export PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME%%.*} $(eval "echo ${MYPSDIR}")\007"'

Вот как это выглядит в действии. Зеленый 0 - код возврата последней команды:

enter image description here

5 голосов
/ 16 апреля 2011
echo -n $PWD | sed -re "s|(~?/[^/]*/).*(.{$pwd_length})|\1...\2|"

sed с -r только для удобства, позволяет опустить обратную косую черту перед скобками и "|" в качестве разделителя тоже только для удобства - потому что мы хотим использовать косую черту внутри команды. Я полагаю, ваш домашний браузер также отображается как ~, поэтому ~ / foo / bar / baz / должен заканчиваться на ~ / foo /.../ baz, а / foo / bar / baz / как /foo/.../baz /.

Итак, мы берем необязательный ~, за которым следует косая черта, имя, косая черта как \ 1, затем что-то, а затем остальные как \ 2.

3 голосов
/ 06 ноября 2015

Другой подход, все еще использующий sed и awk для генерации приглашения. Это преобразует ваш каталог $HOME в ~, покажет вам ваш корневой каталог, ваш самый низкий уровень (текущий каталог) и его родителя, разделенные .. для каждого каталога между ними.

Внутри вашего .bashrc (или .bash_profile на OS X):

function generate_pwd {
  pwd | sed s.$HOME.~.g | awk -F"/" '
  BEGIN { ORS="/" }
  END {
  for (i=1; i<= NF; i++) {
      if ((i == 1 && $1 != "") || i == NF-1 || i == NF) {
        print $i
      }
      else if (i == 1 && $1 == "") {
        print "/"$2
        i++
      }
      else {
        print ".."
      }
    }
  }'
}
export PS1="\$(generate_pwd) -> "

Сценарий использует встроенную в awk переменную NF (количество полей) и позиционные переменные ($1, $2 ...) для печати каждого поля (имя каталога), разделенного переменной ORS (разделитель выходных записей). Он сворачивает внутренние каталоги в .. в вашем приглашении.

Пример использования:

~/ -> cd Documents/
~/Documents/ -> cd scripts/
~/Documents/scripts/ -> cd test1/
~/../scripts/test1/ -> cd test2
~/../../test1/test2/ -> pwd
/Users/Brandon/Documents/scripts/test1/test2
~/../../test1/test2/ -> cd test3/
~/../../../test2/test3/ -> cd test4/
~/../../../../test3/test4/ -> pwd
/Users/Brandon/Documents/scripts/test1/test2/test3/test4
~/../../../../test3/test4/ -> cd /usr/
/usr/ -> cd local/
/usr/local/ -> cd etc/
/usr/local/etc/ -> cd openssl/
/usr/../etc/openssl/ -> cd private/
/usr/../../openssl/private/ ->
1 голос
/ 31 марта 2015

Помимо встроенного в bash решения, использующего PROMPT_DIRTRIM, вы можете попробовать $(pwd | tail -c16), что немного проще, чем большинство других ответов, но дает только последние 16 символов текущего каталога.Конечно, замените 16 на любое число, которое вы хотите.

0 голосов
/ 24 февраля 2019

https://github.com/chrissound/SodiumSierraStrawberry

Позволяет вам обрезать путь как:

От: / Главная / натрия / Проекты / Personal / Sierra / Super / Long / Path / HolyAvacado

Кому: »Проекты / Sie… / Sup… / Lon… / Pat… / HolyAvacado /

0 голосов
/ 26 августа 2018
generatePwd(){
  set -- "`pwd | sed -e s.${HOME}.~.g`"
  IFS="/"; declare -a array=($*)
  srt=""
  count=0
  for i in ${!array[@]}; do
      # echo ${array[i]} - $i/${#array[@]}
      if [[ $i == 0 ]]; then
        srt+=""
      elif [[ $i == $((${#array[@]}-1)) ]] || [[ $i == $((${#array[@]}-2)) ]]; then
          srt+="/${array[i]}"
      else
        count=$((${count}+1))
      fi
  done
  if [[ $count != 0 ]]; then
    srt="${array[0]}/.$count.$srt"
  else
    srt="${array[0]}$srt"
  fi
  echo "${srt}"
}

экспорт PS1

PS1="\$(generatePwd)"

Консоль

$ ~/.3./machine-learning/deep-learning-computer-vision
0 голосов
/ 03 июля 2015

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

### SET MY PROMPT ###
if [ -n "$PS1" ]; then
    # A temporary variable to contain our prompt command
    NEW_PROMPT_COMMAND='
        pwd_short=${PWD/#$HOME/\~};
        if [ ${#pwd_short} -gt 53 ]; then
            TRIMMED_PWD=${pwd_short: 0: 25}...${pwd_short: -25}
        else
            TRIMMED_PWD=${pwd_short}
        fi
    '

    # If there's an existing prompt command, let's not 
    # clobber it
    if [ -n "$PROMPT_COMMAND" ]; then
        PROMPT_COMMAND="$PROMPT_COMMAND;$NEW_PROMPT_COMMAND"
    else
        PROMPT_COMMAND="$NEW_PROMPT_COMMAND"
    fi

    # We're done with our temporary variable
    unset NEW_PROMPT_COMMAND

    # Set PS1 with our new variable
    # \h - hostname, \u - username
    PS1='\u@\h: $TRIMMED_PWD\$ '
fi

добавлено в файл .bashrc.Все части подсказки обновлены правильно.Первая часть сокращается, если вы находитесь в своем домашнем каталоге. Пример:

user @ computer: ~ / misc / projs / solardrivers ... src / com / mycompany / handles $

0 голосов
/ 06 июня 2015

Почему бы просто не использовать ${string:position:length}?Вы можете сделать ${string:-$max_chars}, чтобы получить последний ${max_chars} строки.

обратите внимание на отрицательное значение

...