wake-up-neo.com

Bash: benutzerdefinierte PS1 mit Nice-Arbeitsverzeichnispfad

Ich benutze Ubuntu und bin müde von diesen langen Aufforderungen in bash, wenn ich mit einer tiefen Verzeichnishierarchie arbeite. Ich möchte also meine PS1 überarbeiten, um den Teil des Arbeitsverzeichnisses folgendermaßen zu verkürzen:

Zur Zeit habe ich:

[email protected]:~/workspace/projects/project1/folder1/test$

und hätte gerne:

[email protected]:~/workspace/.../folder1/test$

Das Abschneiden würde auftreten, wenn len ($ PWD) einen bestimmten Schwellenwert überschreitet. Ich möchte immer die erste Pfadkomponente und mindestens eine letzte Pfadkomponente beibehalten. Fügen Sie dann, wenn der Platz es zulässt, weitere Komponenten hinzu.

Das ist was ich momentan habe. Es funktioniert, aber: 1) behält die erste Pfadkomponente nicht bei, 2) respektiert den Schnittpfad an Grenzen nicht:

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

Und das Ergebnis:

[email protected]:...sth/folder1/sample$ 

Danke im Voraus!

51
pajton

Betrachten Sie dieses Skript mit awk anstelle von sed für Ihren Fall:

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

Für das Beispiel des Verzeichnisses ~/workspace/projects/project1/folder1/test wird PS1 folgendermaßen erstellt: ~/workspace/.../folder1/test

AKTUALISIEREN

Mit der obigen Lösung wird Ihre Eingabeaufforderung festgelegt. Wie Sie jedoch in Ihrem Kommentar festgestellt haben, ändert sich die PS1 NICHT dynamisch, wenn Sie das Verzeichnis wechseln. Hier ist also die Lösung, die PS1 dynamisch setzt, wenn Sie das Verzeichnis wechseln.

Fügen Sie diese 2 Zeilen in Ihre .bashrc-Datei ein:

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}")$ '

Die Bedingung if (NF > 4 && length($0) > 14) in awk wendet nur eine spezielle Behandlung an, wenn Ihr aktuelles Verzeichnis mehr als 3 Verzeichnisse enthält UND wenn die Länge von $PWD mehr als 14 Zeichen beträgt, andernfalls wird PS1 als $PWD beibehalten. 

beispiel: Wenn das aktuelle Verzeichnis ~/workspace/projects/project1$ ist, wird PS1 ~/workspace/projects/project1$ sein.

Der Effekt von oben in .bashrc wird auf Ihrer PS1 wie folgt aussehen:

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

Beachten Sie, wie sich die Eingabeaufforderung ändert, wenn Sie das Verzeichnis wechseln. Lassen Sie mich wissen, ob dies nicht das ist, was Sie wollten.

45
anubhava

Für Benutzer, die nach einer viel einfacheren Lösung suchen und nicht den Namen des ersten Verzeichnisses im Pfad benötigen, bietet Bash integrierte Unterstützung für die Verwendung der Variablen Prompt_DIRTRIM. Aus der Dokumentation :

Prompt_DIRTRIM

Bei einer Zahl größer als Null wird der Wert als Anzahl nachfolgender Verzeichniskomponenten verwendet, die beim Erweitern der Escape-Zeichenfolgen für\w und\W beibehalten werden sollen (siehe Aufforderung drucken). Entfernte Zeichen werden durch eine Ellipse ersetzt. 

Zum Beispiel:

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

Nachteil: Es hängt von der Verzeichnisebene ab, nicht von der Länge des Pfads, die Sie möglicherweise nicht möchten.

Upside: Es ist sehr einfach. Fügen Sie einfach export Prompt_DIRTRIM=2 zu Ihrem .bashrc hinzu.

113
imgx64

Dies verwende ich basierend auf den Lösungen von anubhava. Es legt sowohl die Aufforderung als auch den Windows-Titel fest. Das awk-Skript ist besser lesbar, sodass es leicht angepasst/angepasst werden kann.

Der Pfad wird gefaltet, wenn er mehr als 16 Zeichen und 4 Ebenen tief ist. Außerdem zeigt es in der ... an, wie viele Verzeichnisse gefaltet wurden, sodass Sie ein Gefühl dafür bekommen, wie tief der Pfad ist, dh: ~/usr/..4../path2/path1 zeigt an, dass 4 Ebenen gefaltet wurden. 

# 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 [email protected] ~]$
# return code is in green, [email protected] is in bold/white
export PS1='[\[\033[1;32m\]$?\[\033[0;0m\] \[\033[0;1m\]\[email protected]\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"'

So sieht es in Aktion aus. Die grüne 0 ist der Rückkehrcode des letzten Befehls:

 enter image description here

9
raychi
echo -n $PWD | sed -re "s|(~?/[^/]*/).*(.{$pwd_length})|\1...\2|"

mit -r nur für die Bequemlichkeit, erlaubt Backslash vor Klammern und "|" als Trennzeichen nur zur Vereinfachung - weil wir den Schrägstrich innerhalb des Befehls verwenden möchten. Ich schätze, Ihr Zuhause wird auch als ~ angezeigt, also sollte ~/foo/bar/baz/in ~/foo /.../ baz und/foo/bar/baz/als /foo/.../baz enden /. 

Also nehmen wir ein optionales ~, gefolgt von einem Schrägstrich, einem Namen, einem Schrägstrich als\1, dann etwas und dem Rest als\2. 

5
user unknown

Ein anderer Ansatz, der noch sed und awk verwendet, um die Eingabeaufforderung zu generieren. Dadurch wird Ihr $HOME-Verzeichnis in ~ konvertiert, und Sie werden Ihr Stammverzeichnis, Ihre unterste Ebene (aktuelles Verzeichnis) und das übergeordnete Verzeichnis angezeigt, getrennt durch .. für jedes Verzeichnis dazwischen.

In Ihrem .bashrc (oder .bash_profile unter 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) -> "

Das Skript verwendet die eingebaute Variable NF (Anzahl der Felder) und Positionsvariablen ($1, $2 ...) von awk, um jedes Feld (Verzeichnisname) durch die Variable ORS (Ausgabedatentrennzeichen) getrennt zu drucken. Die inneren Verzeichnisse werden in Ihrer Eingabeaufforderung zu .. zusammengefasst.

Beispiel davon in Verwendung:

~/ -> 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/ ->
3
Brandon

Abgesehen von der bash-builtin-Lösung, die Prompt_DIRTRIM verwendet, können Sie $(pwd | tail -c16) ausprobieren. Dies ist ein wenig einfacher als die meisten anderen Antworten, gibt jedoch nur die letzten 16 Zeichen des aktuellen Verzeichnisses an. Natürlich können Sie 16 durch eine beliebige Nummer ersetzen.

1
Sebastian Mach

Nicht so sehr von den bisherigen Lösungen. Möglicherweise jedoch etwas lesbarer/bearbeitbarer. Es gibt jedoch keine Lösung für die Begrenzung des Ordnernamens, sondern nur die Länge der Eingabeaufforderung.

### 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='\[email protected]\h: $TRIMMED_PWD\$ '
fi

zur .bashrc-Datei hinzugefügt . Alle Teile der Aufforderung werden ordnungsgemäß aktualisiert. Der erste Teil wird gekürzt, wenn Sie sich in Ihrem Heimatverzeichnis befinden. Beispiel:

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

0
karnbo

Warum verwenden Sie nicht einfach ${string:position:length}? Sie können ${string:-$max_chars} verwenden, um den letzten ${max_chars} der Zeichenfolge zu erhalten. 

den negativen Wert beachten

0
Naus Caligo

https://github.com/chrissound/SodiumSierraStrawberry

Ermöglicht das Abschneiden eines Pfads wie:

Von:/home/natrium/Projekte/Persönliches/Sierra/Super/Lang/Pfad/HolyAvacado

An: »Projekte/Sie…/Sup…/Lon…/Pat…/HolyAvacado /

0
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 exportieren

PS1="\$(generatePwd)"

Konsole

$ ~/.3./machine-learning/deep-learning-computer-vision