디렉토리 트리 / 파일 이름 사용시 컴팩트 bash 프롬프트


16

우분투 14.04와 가진 시스템에서 bash, 나는이 PS1다음과 같은 내용으로 끝나는 변수를 :

\u@\h:\w\$

프롬프트가 다음과 같이 표시되도록

user@machinename:/home/mydirectory$

그러나 때로는 현재 디렉토리의 이름이 길거나 이름이 긴 디렉토리 안에 있으므로 프롬프트가 다음과 같이 표시됩니다.

user@machinename:/home/mydirectory1/second_directory_with_a_too_long_name/my_actual_directory_with_another_long_name$

이것은 터미널의 줄을 채우고 커서는 다른 줄로 이동하여 성가시다.

대신에 다음과 같은 것을 얻고 싶습니다

user@machinename:/home/mydirectory1/...another_long_name$

PS1디렉토리 이름을 "wrap"및 "compact" 하도록 변수 를 정의하여 특정 문자 수를 초과하지 않도록하여 짧은 프롬프트를 얻는 방법이 있습니까?


1
다행스럽게도 쉘 프롬프트를 사용자 정의하는 방법을 읽은 곳을 기억합니다. tldp.org/HOWTO/Bash-Prompt-HOWTO/x783.html 감사 합니다. Giles Orr, Bash Prompt HOWTO의 저자이자 기여한 사람들에게 감사드립니다.
stemd

참조 unix.stackexchange.com/a/216871/117549 (KSH-기반으로하지만, 유사한 아이디어)
제프 쉘러

답변:


16

우선, 단순히 \wwith 를 변경하고 싶을 수도 있습니다 \W. 이렇게하면 현재 디렉토리의 이름 만 인쇄되고 전체 경로는 인쇄되지 않습니다.

terdon@oregano:/home/mydirectory1/second_directory_with_a_too_long_name/my_actual_directory_with_another_long_name $ PS1="\u@\h:\W \$ "
terdon@oregano: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\]\u@\h\[\033[01;34m\] ${left}...${right} \$\[\033[00m\] "
        else
                PS1="\[\033[01;33m\]\u@\h\[\033[01;34m\] \w \$\[\033[00m\] "
        fi


}
PROMPT_COMMAND=get_PS1

효과는 다음과 같습니다.

terdon@oregano ~ $ cd /home/mydirectory1/second_directory_with_a_too_long_name/my_actual_directory_with_another_long_name
terdon@oregano /home...th_another_long_name $ 

10

문자 반환을 추가하는 것이 나의 주요 해결책입니다.

그래서 내 프롬프트 (다른 ​​것들도 있고 더 길어집니다)는 다음과 같습니다.

여기에 이미지 설명을 입력하십시오

$가 새 줄로 반환되는 것을 알 수 있습니다

나는 이것을 달성한다

HOST='\[\033[02;36m\]\h'; HOST=' '$HOST
TIME='\[\033[01;31m\]\t \[\033[01;32m\]'
LOCATION=' \[\033[01;34m\]`pwd | sed "s#\(/[^/]\{1,\}/[^/]\{1,\}/[^/]\{1,\}/\).*\(/[^/]\{1,\}/[^/]\{1,\}\)/\{0,1\}#\1_\2#g"`'
PS1=$TIME$USER$HOST$LOCATION'\n\$ '

별도의 줄에 있더라도 다음과 같은 슈퍼 긴 디렉토리 트리는

/home/durrantm/Dropbox/96_2013_archive/work/code/ruby__rails ~에 단축되다

/home/durrantm/Dropbox/_/code/ruby__rails

예를 들어 "상위 3 개 디렉토리 / _ / 아래 두 개의 디렉토리"

이렇게하면 디렉토리 트리 길이로 인해 줄이 너무 길어지지 않습니다. 항상 전체 디렉토리 트리를 원하면 LOCATION을 조정하십시오.

LOCATION=' \[\033[01;34m\]`pwd`'


1
프롬프트에 실제로 $ ? (참조 이것을 .)
G-남자 '분석 재개 모니카'말한다

마지막에 \ $를 추가했습니다. 감사합니다. 그것은 일반적으로 나는 또한 내 자식 분기를 보여주기 때문에 여기에 너무 자세한 내용입니다
Michael Durrant

1
뭐? 줄 바꿈이 없습니까? SGR0이 없습니까?
G-Man, 'Reinstate

라인 피드 추가
Michael Durrant

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 "\u@\h:$nPWD\$ "

~ / .bash_profile에 추가되었습니다.

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

출력은 다음과 같습니다

user@machinename:/home/mydirectory1/...another_long_name$

1

긴 경로를 줄이는 솔루션은 아니지만 모든 경로 정보를 표시하면서 더 나은 개요를 얻는 편리한 방법은 마지막 문자 앞에 줄 바꿈을 추가하는 것입니다. 이렇게하면 경로가 줄 바꿈되기에 커서가 항상 동일한 열에서 시작하지만 콘솔 창은 이전 행을 너무 빨리 스크롤하지 않을 정도로 높아야합니다. 더 명확하게 색상 코드를 제거했습니다.

murphy@seasonsend:~
$ echo $PS1
\u@\h:\w\n\$
murphy@seasonsend:~
$ 

1

나는 이것을 사용하여 여러 줄로 감싸서 길이만큼 들여 쓰기 user@host때문에 전류 PS1가 효과적으로 ' \u@\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(user@host)

        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"보이지 않는"이스케이프도 보존됨을 의미 xterm합니다.

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

결과적으로 80 열 터미널이 생성됩니다.

mr@onomatopoeia:~$ cd /usr/src/linux/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace
mr@onomatopoeia:/usr/src/linux/tools/perf/scripts/perl/Perf-Trace-Util/lib/...
               > .../Perf/Trace$ _

이것은 사용 된 bash-3.2에서 작동합니다 printf -v var. 인해 다양한 복잡성 은 다른 변화에 대한 몇 가지 조정을해야합니다 PS1.

( xterm 제목 표시 줄 의 경로는 줄 바꿈되거나 생략되지 않으며 여기에 다른 답변 중 하나를 위 함수에 통합하여 수행 할 수 있습니다.)


0

대안으로, 내 .zshrc에서 픽셀 너비가 특정 너비를 초과하면 각 디렉토리의 첫 글자를 약어로 사용합니다.

user@machinename:/home/mydirectory1/second_directory
user@machinename:/home/mydirectory1/second_directory/my_actual_directory

된다 :

user@machinename:/h/mydirectory1/second_directory
user@machinename:/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)


PS1 프롬프트를 정의하는 방법에 대해 OP가 제기 한 질문에 어떻게 적용됩니까?
Anthon

명확성을 위해 편집 된 $ t는 PS1이 됨
Richard

0

이 Python 스크립트를 사용해보십시오 . 질문에서 원하는 방식으로 경로 이름의 개별 섹션을 잘라냅니다. 또한 3 개 대신 1 개의 열만 차지하는 유니 코드 줄임표를 사용합니다.

경로의 출력 예 (한글 30 자 제한) :

/home/mydir…/second…/my_actua

이 솔루션은를 사용하여 디렉토리 이름에서 유니 코드를 올바르게 처리한다는 점에 주목할 가치가 wcswidth있습니다. ${#PWD}다른 답변에서 사용한 UTF-8 문자가 포함 된 경로의 시각적 너비를 잘못 판단합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.