निर्देशिका पेड़ / फ़ाइल नाम का उपयोग करते समय कॉम्पैक्ट बैश प्रॉम्प्ट


16

Ubuntu 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चर को "रैप" और "कॉम्पैक्ट" निर्देशिका नाम को परिभाषित करने का एक तरीका है , कभी-कभी वर्णों की एक निश्चित संख्या से अधिक नहीं, एक छोटा संकेत प्राप्त करना?


1
सौभाग्य से मुझे याद है कि मैंने शेल प्रॉम्प्ट को कैसे कस्टमाइज़ किया है, यह पढ़ा: tldp.org/HOWTO/Bash-Prompt-HOWTO/x783.html बैश प्रॉम्प्ट HOWTO के लेखक जाइल्स ऑर के पास जाएं और लोगों ने भी इसमें योगदान दिया।
तने

यह भी देखें unix.stackexchange.com/a/216871/117549 (ksh आधारित है, लेकिन इसी तरह के विचार)
जेफ स्कालर

जवाबों:


16

सबसे पहले, आप बस के \wसाथ बदलना चाहते हो सकता है \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चर का उपयोग कर सकते हैं । यह एक विशेष बैश वैरिएबल है जिसका मान प्रत्येक प्रॉम्प्ट दिखाए जाने से पहले कमांड के रूप में निष्पादित किया जाता है। इसलिए, यदि आप उस फ़ंक्शन को सेट करते हैं जो आपके वर्तमान निर्देशिका के पथ की लंबाई के आधार पर अपना वांछित संकेत सेट करता है, तो आप उस प्रभाव को प्राप्त कर सकते हैं जो आप बाद में कर सकते हैं। उदाहरण के लिए, इन पंक्तियों को अपने में जोड़ें ~/.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
आपके प्रॉम्प्ट में वास्तव में कहां शामिल है $ ? (देखें यह ।)
जी-मैन कहते हैं 'को फिर से बहाल मोनिका'

अंत में \ $ जोड़ा गया, धन्यवाद। ऐसा इसलिए था क्योंकि आम तौर पर मैं अपनी git ब्रांच भी दिखाता हूं, लेकिन यहां बहुत विस्तार है
माइकल डुरंट

1
क्या? कोई नई रेखा नहीं? नहीं SGR0?
जी-मैन ने कहा कि मोनिका '

लाइनफीड को जोड़ा
माइकल डुरंट ने

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

लंबे रास्तों को छोटा करने का कोई समाधान नहीं, लेकिन सभी पथ सूचनाओं को दृष्टिगत रखते हुए एक बेहतर अवलोकन प्राप्त करने का एक सुविधाजनक तरीका, अंतिम चरित्र से पहले एक नई पंक्ति जोड़ रहा है। इस तरह से कर्सर हमेशा एक ही कॉलम में शुरू होता है, भले ही मार्ग चारों ओर लपेटने के लिए पर्याप्त लंबा हो, लेकिन आपकी कंसोल विंडो (s) इतनी अधिक होनी चाहिए कि पिछली पंक्तियों को भी जल्दी से स्क्रॉल न करें। मैंने अधिक स्पष्टता के लिए रंग कोड हटा दिए:

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)


पीएस 1 प्रॉम्प्ट को कैसे परिभाषित किया जाए, यह ओपी के प्रश्न पर कैसे लागू होता है?
एंथन

स्पष्टता के लिए संपादित, $ t PS1 बन जाता है
रिचर्ड

0

इस पायथन लिपि का उपयोग करके देखें । यह पथ नाम के अलग-अलग वर्गों को काट देता है, ठीक उसी तरह जैसे आप अपने प्रश्न में कैसे चाहते थे। यह यूनिकोड इलिप्सिस का भी उपयोग करता है जो तीन के बजाय केवल एक कॉलम लेता है।

अपने पथ के लिए उदाहरण आउटपुट (जब 30 वर्णों की सीमा दी जाती है):

/home/mydir…/second…/my_actua

यह ध्यान देने योग्य है कि यह समाधान उपयोग करके निर्देशिका नामों में यूनिकोड को सही ढंग से संभालता है wcswidth${#PWD}, जो अन्य उत्तरों का उपयोग करते हैं, किसी भी पथ की दृश्य चौड़ाई को बुरी तरह से गलत कर देंगे जिसमें UTF-8 वर्ण शामिल हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.