Bir dizin ağacı / dosya adı kullanırken kompakt bash istemi


16

Ubuntu 14.04 ve bir sistemde , aşağıdaki içeriklerle biten değişken bashvar PS1:

\u@\h:\w\$

böylece bilgi istemi şu şekilde görünür:

user@machinename:/home/mydirectory$

Bununla birlikte, bazen, geçerli dizinin uzun bir adı vardır veya uzun adlara sahip dizinlerin içinde bulunur, böylece istem

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

Bu terminaldeki çizgiyi dolduracak ve imleç can sıkıcı başka bir satıra gidecektir.

Bunun yerine şöyle bir şey elde etmek istiyorum

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

Tanımlamak için bir yol var mı PS1daha kısa istemi alma, karakter belirli sayıda aşan asla "sargı" ve "kompakt" dizin adı değişkeni?


1
Neyse ki kabuk komut istemini nasıl özelleştirebileceğimi nereden okuduğumu hatırlıyorum: tldp.org/HOWTO/Bash-Prompt-HOWTO/x783.html Teşekkürler Bash Prompt HOWTO'nun yazarı Giles Orr ve ona katkıda bulunan insanlar.
stemd

Ayrıca bkz. Unix.stackexchange.com/a/216871/117549 (ksh tabanlı, ancak benzer bir fikir)
Jeff Schaller

Yanıtlar:


16

Her şeyden önce, sadece değiştirmek isteyebilirsiniz \wile \W. Bu şekilde, tüm yolu değil, yalnızca geçerli dizinin adı yazdırılır:

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 $ 

Dizin adının kendisi çok uzunsa, bu hala yeterli olmayabilir. Bu durumda, PROMPT_COMMANDdeğişkeni bunun için kullanabilirsiniz . Bu, değeri her komut isteminden önce komut olarak yürütülen özel bir bash değişkenidir. Bu nedenle, bunu geçerli dizininizin yolunun uzunluğuna göre istediğiniz istemi ayarlayan bir işleve ayarlarsanız, peşinde olduğunuz efekti elde edebilirsiniz. Örneğin, şu satırları ekleyin ~/.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

Etkisi şöyle:

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

Bir karakter dönüşü eklemek buna ana çözümüm

Yani istemim (çok daha başka şeyler de var, daha uzun yapma) şöyle görünür:

resim açıklamasını buraya girin

$ 'In yeni bir satır olarak döndüğünü fark edeceksiniz

Bunu ile başarım

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\$ '

Ayrı bir satırda olmasına rağmen, süper uzun dizin ağaçlarının

/home/durrantm/Dropbox/96_2013_archive/work/code/ruby__rails kısaltılmış

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

yani "üst 3 dizin / _ / alt iki dizin" hangi genellikle umurumda olduğunu

Bu, dizin ağacı uzunluğu nedeniyle çizginin hiçbir zaman çok uzun olmamasını sağlayacaktır. Her zaman tam dizin ağacının LOCATION ayarını yapmasını istiyorsanız, yani

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


1
İsteminiz aslında nerede $ ? (Bakınız , bu .)
G-Man 'eski haline Monica' isimli

Sonunda \ $ eklendi, teşekkürler. çünkü normalde git şubemi de gösteriyorum ama burası için çok fazla ayrıntı var
Michael Durrant

1
Ne? Yeni satır yok mu? SGR0 yok mu?
G-Man,


3

~ / .Bash_prompt oluşturuldu:

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 dosyama eklendi:

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

Çıktı:

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

1

Uzun yolları kısaltmak için bir çözüm değil, ancak tüm yol bilgilerini görünür tutarken daha iyi bir genel bakış elde etmenin uygun bir yolu, son karakterden önce yeni satır eklemek. Bu şekilde, imleç, yol etrafı sarmak için yeterince uzun olsa bile, her zaman aynı sütunda başlar, ancak konsol pencereleriniz önceki satırları çok hızlı kaydırmayacak kadar yüksek olmalıdır. Daha fazla netlik için renk kodlarını kaldırdım:

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

1

Bunu kullanıyorum, uzunluğa göre birden fazla satıra ve girintilere sarılıyor, user@hostböylece akımın PS1etkili olduğunu varsayar ' \u@\h:\w$'. Yolu kısaltmaz ve geçerli terminal genişliğine uyum sağlar. Sadece yolu böler /, bu yüzden gerçekten uzun dizinlerle zarif bir şekilde uğraşmaz (ancak seçim / kopya için boşlukları korur). Giriş için her zaman en az 20 karakterlik bir alanınızın olmasını sağlar.

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

Bu, sihri \w(yalnızca bununla eşleşir \w$) çıkarıp PS1değiştirerek ve $PWDardından düz bir karakter dizisi olarak sararak çalışır. PS1Kaydedilen orijinal değerden her seferinde yeniden hesaplar _PS1, bu da "görünmez" kaçışların da korunduğu, tam orijinal bilgi istemi dizemin xtermve kalın bilgi isteminin:

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

Ve sonuç 80 sütunlu bir terminal ile sonuçlanır:

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$ _

Bu printf -v var, kullanıldığı gibi bash-3.2'den çalışır . Çeşitli karmaşıklıklar nedeniyle, diğer varyasyonları için bazı ayarlamalar yapılması gerekecektir PS1.

( Xterm başlık çubuğundaki yol ne sarılmış ne de kısaltılmıştır, buradaki diğer cevaplardan biri yukarıdaki işleve dahil edilerek yapılabilecek bir şeydir.)


0

Alternatif olarak, .zshrc'de, piksel genişliği belirli bir genişliğin üzerindeyse, her dizinin ilk harfini kısaltırım:

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

dönüşür:

user@machinename:/h/mydirectory1/second_directory
user@machinename:/h/m/s/my_actual_directory

İşte bunu yapmak için zsh işlevi:

     # 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

Aslında bunu terminal başlığını güncellemek için kullanıyorum, böylece çoklu sekmelerle hangi sekmenin hangisi olduğunu düz tutabilirim. Bunu yapmak için tam .zshrc burada .

Bağlamı koruduğu ve zsh cinsinden bir dizini aynı biçimde hızlı bir şekilde sekmeyi tamamlamanıza izin verdiği için bu çok kullanışlıdır. (örneğin, yazmak cd /h/m/s/<tab>otomatik olarak tamamlanacak cd /home/mydirectory1/second_directory)


Bu OP'nin PS1 istemini nasıl tanımlayacağı sorusu için nasıl geçerlidir?
Anthon

Netlik için düzenlendi, $ t PS1 oldu
Richard

0

Bu Python komut dosyasını kullanmayı deneyin . Sorunuzda nasıl olmasını istediğiniz gibi yol adının ayrı bölümlerini keser. Ayrıca üç yerine yalnızca bir sütun alan unicode üç nokta kullanır.

Yolunuz için örnek çıktı (30 karakterlik bir sınır verildiğinde):

/home/mydir…/second…/my_actua

Bu çözümün Unicode'u dizin adlarında kullanarak doğru şekilde işlediğini belirtmek gerekir wcswidth. ${#PWD}diğer yanıtların kullandığı UTF-8 karakterlerini içeren herhangi bir yolun görsel genişliğini yanlış değerlendirir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.