Frage Bash-Prompt: Wie haben Sie die Initialen des Verzeichnispfads?


Ich habe normalerweise nur den Namen des aktuellen Verzeichnisses in meiner Bash-Eingabeaufforderung (PS1='\u@\h:\W$ '), wenn ich drin bin ~/projects/superapp/src/ Ich bekomme:

hamish@host:src$ 

Allerdings möchte ich einen Hinweis auf den vollständigen Pfad haben, ohne den vollständigen Pfad zu haben. Ich habe Screenshots gesehen, wo Leute hätten

hamish@host:~/p/s/src$ 

wenn im obigen Beispielverzeichnis. Welchen Wert würde PS1 also geben? Oder, wenn das nicht funktioniert, welches Skript brauche ich in meinem .bashrc um das zu produzieren?


4
2017-08-24 21:34


Ursprung


Das ist eine gute Frage, aber es ist auch ein exaktes Duplikat einer Frage (bereits beantwortet) auf Stack Overflow: stackoverflow.com/questions/1616678/bash-pwd-verkürzung - Telemachus
Es ist nicht wirklich ein exaktes Duplikat, obwohl es ähnlich ist. Aber wenn ich das durchschaue, kann ich nicht genau sehen, wie ich genau das mache, was ich will - das ist keine feste Länge, sondern nur Initialen. Ich könnte es versuchen und die Antwort hier posten, wenn es mir gelingt. - Hamish Downer
Meinetwegen. Ich habe eine Antwort geschrieben, basierend auf diesem Thread. - Telemachus
Es ist auch ein Duplikat von dieses. - Dennis Williamson
@Telemachus - es ist gut, auf eine Lösung von einer anderen Seite zu verweisen, aber es gibt keinen Grund, dass eine Frage nicht auf beiden Seiten existieren kann, wenn sie auf beiden Seiten ein Thema ist. Diese Frage ist beim Super User Thema, sie kann und soll hier beantwortet werden. - Gnoupi


Antworten:


Ok, ich bin neugierig geworden, also hier ist eine Lösung:

  1. Erstellen Sie zunächst eine Funktion mit einer kleinen Optimierung von William Purplells Antwort zum SO Frage Ich verlinke in meinem Kommentar oben.
  2. Als nächstes setze das in deinen $ PS1 als \$(function_name) an der richtigen Stelle.

Als Beispiel:

short_pwd() {
    cwd=$(pwd | perl -F/ -ane 'print join( "/", map { $i++ < @F - 1 ?  substr $_,0,1 : $_ } @F)')
    echo -n $cwd
}
# later in your .bashrc
PS1="\u \$(short_pwd) \$ "

Ich hoffe, dass jemand, der besser mit Bash-Scripting umgehen kann als ich, Wege vorschlagen kann, um die Funktion aufzuräumen, aber dies sollte Ihnen eine Vorstellung davon geben, wie die Ausgabe eines anderen Befehls (oder Bash-Funktion) in einer Eingabeaufforderung verwendet werden kann. Siehe auch hier: http://www.linux.org/docs/ldp/howto/Bash-Prompt-HOWTO/x279.html

Aufgrund Ihres Kommentars habe ich erneut gesucht und festgestellt, dass meine Lösung doppelt zitiert werden muss. Wenn Sie eine solche Funktion angeben, funktioniert sie überhaupt nicht.


2
2017-08-24 22:13



Ich weiß nicht, Perl kann die allgemeine Lösung nicht beurteilen, aber ich denke, Sie müssten es bearbeiten, um zu verwenden PROMPT_COMMAND wie in meiner Lösung sonst PS1 wird beim Start von bash gesetzt und ändert sich nicht, wenn Sie das Verzeichnis wechseln. - Hamish Downer
@ Hamish Nein, das ist falsch. Das ändert sich wie du cd. Ich benutze es jetzt. (Und das ist keine Perl-Sache. Es hat damit zu tun, wie PS1 funktioniert. Sie können dynamische Informationen dort in einer Funktion über haben \$(function). - Telemachus
@ Hamish Aber du hast mir geholfen zu sehen, dass ich doppelte Anführungszeichen brauchte, nicht single, wie ich ursprünglich schrieb. Die Eingabeaufforderung, die ich hier teste, beinhaltet Farb-Escapes und ist komplexer, und ich habe es versehentlich mit einfachen Anführungszeichen vereinfacht. Es tut uns leid. - Telemachus
ah interessant, ich muss natürlich ein bisschen mehr über bash lernen ... - Hamish Downer


Ich mag Meowsqueaks Ansatz und versuche, in der Leistung zu bleiben. Aber ich wollte, dass mein Pfad lange Verzeichnisnamen auf ein Zeichen abkürzt.

me@comp:~ $ cd my/path/haslongnames/
me@comp:~my/p/h $

Dies basiert auf der Lösung von meowsqueak. Es könnte einige Verbesserungen / mehr Funktionen aushalten, aber es löst das Grundproblem, ohne sed zu feuern.

Dies ist in einer ausführbaren Datei, zum Beispiel ~ / bin / ps1

# set this to whatever you want:
MAX_PWD_LENGTH=30
function shorten_pwd
{
    # This function ensures that the PWD string does not exceed $MAX_PWD_LENGTH characters
    PWD=$(pwd)

    # determine part of path within HOME, or entire path if not in HOME
    RESIDUAL=${PWD#$HOME}

    # compare RESIDUAL with PWD to determine whether we are in HOME or not
    if [ X"$RESIDUAL" != X"$PWD" ]
    then
        PREFIX="~"
    fi

    # check if residual path needs truncating to keep total length below MAX_PWD_LENGTH
    NORMAL=${PREFIX}${RESIDUAL}
    if [ ${#NORMAL} -ge $(($MAX_PWD_LENGTH)) ]
    then
        newPWD=${PREFIX}
        OIFS=$IFS
        IFS='/'
        bits=$RESIDUAL
        for x in $bits
        do
            if [ ${#x} -ge 3 ]
            then
                NEXT="/${x:0:1}"
            else
                NEXT="$x"
            fi
            newPWD="$newPWD$NEXT"
        done

        IFS=$OIFS
    else
        newPWD=${PREFIX}${RESIDUAL}
    fi

    # return to caller
    echo $newPWD
}
export PS1="\u@\h:$(shorten_pwd) $ "

In meinem .bash_profile habe ich dann

PROMPT_COMMAND="source $HOME/bin/ps1"

3
2017-08-03 17:01



Kannst du mir bitte erklären, wie sich die Funktion nicht in der Leitung beschweren wird: RESIDUAL=${PWD#$HOME}  Selbst der Syntax-Highlighter sagt, dass es mit dem # Kommentar funky ist - stagl
Ehrlich, @stagl, es ist Jahre her, seit ich diese Aufforderung benutzt habe. Ich erinnere mich nicht viel darüber, warum das alles funktioniert. : / - leff
Nachtrag. Habe das gefunden, während ich etwas anderes erforscht habe. gnu.org/software/bash/manual/html_node/...  "Das Wort wird erweitert, um ein Muster zu erzeugen, genau wie bei der Dateinamenerweiterung. Wenn das Muster dem Anfang des erweiterten Werts des Parameters entspricht, ist das Ergebnis der Erweiterung der erweiterte Wert des Parameters mit dem kürzesten Übereinstimmungsmuster (der Fall)" - leff


Ich habe das kürzlich neu geschrieben, basierend auf einem anderen Skript, das ich vor Jahren geschrieben habe - dieses ist so optimiert, dass es innerhalb der Bash so weit wie möglich läuft, um teure Gabeln zu vermeiden. Es war fast 8x schneller als meine alte Funktion, die awk / sed verwendete.

Es bringt schöne Ergebnisse. Es behält den pwd-Teil der Eingabeaufforderung auf nicht mehr als MAX_PWD_LENGTH Zeichen, und wenn Sie sich in einem Unterverzeichnis von $ HOME befinden, wird dies auch deutlich:

Beispiele:

pc770-ubu:~ $ cd ~/a/b/c
pc770-ubu:~/a/b/c $ cd d/e/f
pc770-ubu:~/a/b/c/d/e/f $ cd g
pc770-ubu:~/a/b/c/d/e/f/g $ cd h
pc770-ubu:~/a/b/c/d/e/f/g/h $ cd i
pc770-ubu:~/a/b/c/d/e/f/g/h/i $ cd j
pc770-ubu:~/a/b/c/d/e/f/g/h/i/j $ cd k
pc770-ubu:~/a/b/c/d/e/f/g/h/i/j/k $ cd l
pc770-ubu:~../c/d/e/f/g/h/i/j/k/l $ cd m
pc770-ubu:~../d/e/f/g/h/i/j/k/l/m $ cd n
pc770-ubu:~../e/f/g/h/i/j/k/l/m/n $ cd o
pc770-ubu:~../f/g/h/i/j/k/l/m/n/o $ cd /tmp/a/b/c/d/e/f
pc770-ubu:/tmp/a/b/c/d/e/f $ cd g
pc770-ubu:/tmp/a/b/c/d/e/f/g $ cd h
pc770-ubu:/tmp/a/b/c/d/e/f/g/h $ cd i
pc770-ubu:/tmp/a/b/c/d/e/f/g/h/i $ cd j
pc770-ubu:/../a/b/c/d/e/f/g/h/i/j $ cd k
pc770-ubu:/../b/c/d/e/f/g/h/i/j/k $ cd l
pc770-ubu:/../c/d/e/f/g/h/i/j/k/l $ cd m
pc770-ubu:/../d/e/f/g/h/i/j/k/l/m $ cd
pc770-ubu:~ $ 

Die bash-Funktion (rufen Sie diese beim Erstellen Ihrer PS1-Variablen auf):

# set this to whatever you want:
MAX_PWD_LENGTH=20

function shorten_pwd
{
    # This function ensures that the PWD string does not exceed $MAX_PWD_LENGTH characters
    PWD=$(pwd)

    # if truncated, replace truncated part with this string:
    REPLACE="/.."

    # determine part of path within HOME, or entire path if not in HOME
    RESIDUAL=${PWD#$HOME}

    # compare RESIDUAL with PWD to determine whether we are in HOME or not
    if [ X"$RESIDUAL" != X"$PWD" ]
    then
        PREFIX="~"
    fi

    # check if residual path needs truncating to keep total length below MAX_PWD_LENGTH
    # compensate for replacement string.
    TRUNC_LENGTH=$(($MAX_PWD_LENGTH - ${#PREFIX} - ${#REPLACE} - 1))
    NORMAL=${PREFIX}${RESIDUAL}
    if [ ${#NORMAL} -ge $(($MAX_PWD_LENGTH)) ]
    then
        newPWD=${PREFIX}${REPLACE}${RESIDUAL:((${#RESIDUAL} - $TRUNC_LENGTH)):$TRUNC_LENGTH}
    else
        newPWD=${PREFIX}${RESIDUAL}
    fi

    # return to caller
    echo $newPWD
}

EDIT: Fehler mit absoluter Stringlänge behoben


2
2017-08-25 02:27





PROMPT_DIRTRIM=3

Erzwingt die Erweiterung von \ w auf das Maximum von drei Trailing-Elementen des aktuellen Arbeitsverzeichnispfads, wobei die vorangehende (falls vorhanden) durch "..." ersetzt wird.


2
2018-04-16 14:28





Fügen Sie dieses einfach hinzu (und bearbeiten Sie, wie Sie möchten) zu Ihrem .bashrc:

PS1='\u@\h:`pwd | sed -e "s/\/\(.\)[^\/]\+/\/\1/g"`\$ '

1
2017-08-24 22:29



Ich habe das versucht, aber leider setzt es den Wert von PS1einmal wenn du bash startest und danach nicht mehr aktualisierst. Du wirst also das Verzeichnis wechseln und deine Eingabe wird sich nicht ändern - ich habe diesen Fehler gemacht und dann gespielt und musste mir den Kopf kratzen, um es herauszufinden. Siehe meine (bearbeitete) Antwort für einen Weg um dies zu nutzen PROMPT_COMMAND - Hamish Downer
Nein, es funktioniert für mich, es ändert sich jedes Mal. - cYrus
Und echo $PS1 gibt: \ u @ \ h: 'pwd | sed -e "s / \ / (.) [^ \ /] \ + / \ / \ 1 / g" '\ $ also ist es nicht hart in die Variable kodiert (ich weiß nicht, wie ich dieses Markup überschreiben soll, nur Ersetzen Sie "mit"). - cYrus
Oh ok. Ich lese noch mehr, danke für die Erklärung. - Hamish Downer


Ich habe in der Zwischenzeit ein wenig mehr gegoogelt, und nachdem ich ein paar Suchbegriffe durchgelesen hatte, bin ich rübergekommen Dieser Artikel das erwähnt das Fischschale tut, was ich will, und bietet mir eine Möglichkeit, es zu tun. Ich habe es so modifiziert, dass der Benutzer und der Host ebenfalls angezeigt werden und mit dem ziemlich prägnanten Ergebnis enden:

# abbreviate the dir path
PROMPT_COMMAND='CurDir=`pwd|sed -e "s!$HOME!~!"|sed -re "s!([^/])[^/]+/!\1/!g"`'
PS1="\u@\h:\$CurDir \$ "

Grundsätzlich jedes Mal, wenn die Aufforderung angezeigt wird, PROMPT_COMMAND wird eingestellt $CurDir zu dem abgekürzten Verzeichnispfad, der dann in verwendet wird $PS1. Beachten Sie, dass wenn PROMPT_COMMAND Wenn Sie an einer anderen Stelle stehen, müssen Sie den obigen Befehl an das Ende des Befehls anfügen, dem ein Buchstabe vorangestellt ist ;. Also für das übliche Beispiel, den Titel eines xterm zu setzen, würdest du enden

PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME}: ${PWD/$HOME/~}\007"; CurDir=`pwd|sed -e "s!$HOME!~!"|sed -re "s!([^/])[^/]+/!\1/!g"`'

Einige andere Möglichkeiten, den Weg abzukürzen, finden sich:


1
2017-08-24 22:38





Eine andere Version von @Telemachus short_pwd (), ohne Perl-Anforderung.

short_pwd() {
cwd=$(pwd)

if [ $cwd == $HOME ]; then echo -n "~"; return; fi 
if [ $cwd == "/" ]; then echo -n "/"; fi 

for l in $(echo $cwd | tr "/" "\n"); do 
    echo -n "/"
    echo -n ${l:0:1}
done
echo -n ${l:1}
}

1
2017-09-13 20:05





Versuche dies:

PS1='$(pp="$PWD/" q=${pp/#"$HOME/"/} p=${q%?};((${#p}>19))&&echo "${p::9}…${p:(-9)}"||echo "$p") \$'

Es verwandelt sich

~/.vim/bundle/ack.vim/plugin

zu

.vim/bund…im/plugin

Transfrom

/usr/share/doc/xorg-x11-font-utils-7.5/

zu

/usr/shar…utils-7.5

Und wann $PWD gleich wie $HOME, zeig nichts.

Bonus: Sie können die Anzahl der Länge ändern, die Sie benötigen.


0
2018-05-26 13:18