62 votes

Bash : PS1 personnalisé avec un joli chemin de répertoire de travail

J'utilise Ubuntu et je suis fatigué de ces longues invites dans bash lorsque je travaille avec une hiérarchie de répertoire profonde. J'aimerais donc modifier mon PS1 pour raccourcir la partie du répertoire de travail de la manière suivante :

Actuellement, j'ai :

pajton@dragon:~/workspace/projects/project1/folder1/test$

et que vous aimeriez avoir :

pajton@dragon:~/workspace/.../folder1/test$

La troncature se produirait si len($PWD) dépasse un seuil donné. Je veux toujours garder le premier composant du chemin et au moins un dernier composant du chemin. Puis, si l'espace le permet, ajouter d'autres composants en partant de la droite.

C'est ce que j'ai actuellement. Cela fonctionne, mais : 1) ne garde pas le premier composant du chemin, 2) ne respecte pas le chemin de coupe aux frontières :

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

Et le résultat :

pajton@dragon:...sth/folder1/sample$ 

Merci d'avance !

132voto

imgx64 Points 1362

Pour les personnes qui recherchent une solution beaucoup plus simple et qui n'ont pas besoin du nom du premier répertoire du chemin d'accès, Bash dispose d'un support intégré à l'aide de la fonction PROMPT_DIRTRIM variable. Extrait de la documentation :

PROMPT_DIRTRIM

Si elle est définie comme un nombre supérieur à zéro, la valeur est utilisée comme le nombre de composants de répertoire de fin à conserver lors de l'expansion de l'objet \w et \W La chaîne d'invite échappe (voir Impression d'une invite). Les caractères supprimés sont remplacés par un point de suspension.

Par exemple :

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

Inconvénient : cela dépend du niveau du répertoire, et non de la longueur du chemin, ce que vous pourriez ne pas vouloir.

Avantage : C'est très simple. Il suffit d'ajouter export PROMPT_DIRTRIM=2 à votre .bashrc .

49voto

anubhava Points 172509

Considérez ce script utilisant awk au lieu de awk pour votre cas :

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

Pour votre exemple de répertoire ~/workspace/projects/project1/folder1/test ça fait PS1 comme : ~/workspace/.../folder1/test

UPDATE

La solution ci-dessus définira votre invite mais comme vous l'avez noté dans votre commentaire, elle ne changera PAS PS1 dynamiquement lorsque vous changez de répertoire. Voici donc la solution qui va définir dynamiquement le PS1 lorsque vous changez de répertoire.

Mettez ces 2 lignes dans votre fichier .bashrc :

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

if (NF > 4 && length($0) > 14) en awk n'appliquera un traitement spécial que si votre répertoire actuel a une profondeur de plus de 3 répertoires ET si la longueur de la variable $PWD est supérieur à 14 caractères, sinon il gardera PS1 comme $PWD .

ex : si le répertoire courant est ~/workspace/projects/project1$ alors la PS1 sera ~/workspace/projects/project1$

L'effet de ce qui précède dans .bashrc sera le suivant sur votre PS1 :

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

Remarquez comment l'invite change lorsque je change de répertoire. Faites-moi savoir si ce n'est pas ce que vous vouliez.

9voto

raychi Points 199

C'est ce que j'ai fait en me basant sur les solutions d'anubhava. Il définit à la fois l'invite et le titre de Windows. L'awk script est plus lisible et peut donc être modifié/personnalisé facilement.

Il tronquera le chemin s'il comporte plus de 16 caractères et 4 niveaux de profondeur. De plus, il indiquera également dans le ... combien de répertoires ont été pliés, afin que vous ayez une idée de la profondeur du chemin, c'est-à-dire que le chemin sera tronqué : ~/usr/..4../path2/path1 indique que 4 niveaux ont été pliés.

# define the awk script using heredoc notation for easy modification
MYPSDIR_AWK=$(cat << 'EOF'
BEGIN { FS = OFS = "/" }
{ 
   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/#$HOME/~}" | awk "$MYPSDIR_AWK")'

# the fancy colorized prompt: [0 user@host ~]%
# return code is in green, user@host is in bold/white
export PS1='[\[\033[1;32m\]$?\[\033[0;0m\] \[\033[0;1m\]\u@\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"'

5voto

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

sed avec -r seulement par commodité, permet d'omettre la barre oblique inverse avant les parenthèses, et "|" comme délimiteur seulement par commodité aussi - parce que nous voulons utiliser la barre oblique à l'intérieur de la commande. Je suppose que votre domicile est également affiché sous forme de ~, donc ~/foo/bar/baz/ devrait se terminer par ~/foo/.../baz, et /foo/bar/baz/ par /foo/.../baz/.

Nous prenons donc un ~ optionnel, suivi d'un slash, d'un nom, d'un slash comme \1 puis quelque chose, puis le reste comme \2.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X