tutorial traduccion programas programacion ejemplos comando bourne again linux bash

linux - traduccion - ejemplos de programas en bash



Bash PWD manteca (8)

Estoy buscando una función de bash que acorte los nombres de ruta largos para evitar que mi variable PS1 se vuelva excesivamente larga. Algo a lo largo de las líneas de:

/this/is/the/path/to/a/really/long/directory/i/would/like/shortened

podría terminar como

/t../i../t../p../to/a/r../l../d../i/w../like/shortened

algo que tomó la ruta y un número máximo aceptable de caracteres para acortar sería perfecto para mi archivo .bashrc.


¿Qué tal un script de Python? Esto acorta los nombres de directorio más largos primero, un carácter a la vez hasta que alcanza su objetivo de longitud o no puede obtener la ruta más corta. No acorta el último directorio en la ruta.

(Comencé a escribir esto en un script de shell simple, pero, bash apesta a la manipulación de cadenas).

#!/usr/bin/env python import sys try: path = sys.argv[1] length = int(sys.argv[2]) except: print >>sys.stderr, "Usage: $0 <path> <length>" sys.exit(1) while len(path) > length: dirs = path.split("/"); # Find the longest directory in the path. max_index = -1 max_length = 3 for i in range(len(dirs) - 1): if len(dirs[i]) > max_length: max_index = i max_length = len(dirs[i]) # Shorten it by one character. if max_index >= 0: dirs[max_index] = dirs[max_index][:max_length-3] + ".." path = "/".join(dirs) # Didn''t find anything to shorten. This is as good as it gets. else: break print path

Ejemplo de salida:

$ echo $DIR /this/is/the/path/to/a/really/long/directory/i/would/like/shortened $ ./shorten.py $DIR 70 /this/is/the/path/to/a/really/long/directory/i/would/like/shortened $ ./shorten.py $DIR 65 /this/is/the/path/to/a/really/long/direc../i/would/like/shortened $ ./shorten.py $DIR 60 /this/is/the/path/to/a/re../long/di../i/would/like/shortened $ ./shorten.py $DIR 55 /t../is/the/p../to/a/r../l../di../i/wo../like/shortened $ ./shorten.py $DIR 50 /t../is/the/p../to/a/r../l../d../i/w../l../shortened


Aquí hay otro giro en la respuesta de Evan:

Este utiliza más (+) en lugar de un asterisco (*) para las rutas truncadas. Reemplaza la ruta de INICIO con ~, y deja el segmento final del directorio intacto. Si el segmento final tiene más de 20 caracteres, lo acorta al bit de tabulación completa y agrega puntos suspensivos (...).

#!/bin/bash # Modified from http://.com/a/1617048/359287 # By Alan Christopher Thomas (http://alanct.com) __pwd_ps1 () { begin="" homebegin="" shortbegin="" current="" end="${2:-$(pwd)}/" # The unmodified rest of the path. end="${end#/}" # Strip the first / shortenedpath="$end" shopt -q nullglob && NGV="-s" || NGV="-u" shopt -s nullglob while [[ "$end" ]] do current="${end%%/*}" # Everything before the first / end="${end#*/}" # Everything after the first / shortcur="$current" for ((i=${#current}-2; i>=0; i--)) do [[ ${#current} -le 20 ]] && [[ -z "$end" ]] && break subcurrent="${current:0:i}" matching=("$begin/$subcurrent"*) # Array of all files that start with $subcurrent (( ${#matching[*]} != 1 )) && break # Stop shortening if more than one file matches [[ -z "$end" ]] && shortcur="$subcurrent..." # Add character filler at the end of this string [[ -n "$end" ]] && shortcur="$subcurrent+" # Add character filler at the end of this string done begin="$begin/$current" homebegin="$homebegin/$current" [[ "$homebegin" =~ ^"$HOME"(/|$) ]] && homebegin="~${homebegin#$HOME}" # Convert HOME to ~ shortbegin="$shortbegin/$shortcur" [[ "$homebegin" == "~" ]] && shortbegin="~" # Use ~ for home shortenedpath="$shortbegin/$end" done shortenedpath="${shortenedpath%/}" # Strip trailing / shortenedpath="${shortenedpath#/}" # Strip leading / [[ ! "$shortenedpath" =~ ^"~" ]] && printf "/$shortenedpath" # Make sure it starts with / [[ "$shortenedpath" =~ ^"~" ]] && printf "$shortenedpath" # Don''t use / for home dir shopt "$NGV" nullglob # Reset nullglob in case this is being used as a function. }

Descargue el script aquí e .bashrc en su .bashrc :

https://raw.github.com/alanctkc/dotfiles/master/.bash_scripts/pwd-prompt.bash

. ~/.bash_scripts/pwd-prompt.bash

Agrega el directorio a tu PS1 esta manera:

export PS1="[other stuff...] /$(__pwd_ps1)/$ "


Aquí hay una solución perl relativamente fácil. Esto es lo suficientemente breve como para que pueda integrarlo directamente en PS1 en lugar de invocar un script. Da todos los caracteres de los nombres truncados en lugar de reemplazarlos con ''.''

$ echo ''/this/is/a/realy/long/path/id/like/shortened'' | perl -F/ -ane ''print join( "/", map { $i++ < @F - 2 ? substr $_,0,3 : $_ } @F)'' /thi/is/a/rea/lon/pat/id/like/shortened

No estoy viendo de inmediato una buena forma de reemplazar los caracteres con ''.'', Pero aquí hay una forma fea:

echo ''/this/is/a/realy/long/path/id/like/shortened'' | perl -F/ -ane ''print join( "/", map { m/(.)(.*)/; $_ = $1 . "." x (length $2 > 2 ? 2 : length $2 ) if $i++ < @F - 2; $_ } @F)'' /t../i./a/r../l../p../i./like/shortened


Aquí hay una solución sólo de bash que te puede gustar. Esto acorta cada parte de la ruta hasta el prefijo más corto que aún se puede completar con pestañas, y usa * en lugar de ... como relleno.

#!/bin/bash begin="" # The unshortened beginning of the path. shortbegin="" # The shortened beginning of the path. current="" # The section of the path we''re currently working on. end="${2:-$(pwd)}/" # The unmodified rest of the path. end="${end#/}" # Strip the first / shortenedpath="$end" # The whole path, to check the length. maxlength="${1:-0}" shopt -q nullglob && NGV="-s" || NGV="-u" # Store the value for later. shopt -s nullglob # Without this, anything that doesn''t exist in the filesystem turns into */*/*/... while [[ "$end" ]] && (( ${#shortenedpath} > maxlength )) do current="${end%%/*}" # everything before the first / end="${end#*/}" # everything after the first / shortcur="$current" shortcurstar="$current" # No star if we don''t shorten it. for ((i=${#current}-2; i>=0; i--)) do subcurrent="${current:0:i}" matching=("$begin/$subcurrent"*) # Array of all files that start with $subcurrent. (( ${#matching[*]} != 1 )) && break # Stop shortening if more than one file matches. shortcur="$subcurrent" shortcurstar="$subcurrent*" done begin="$begin/$current" shortbegin="$shortbegin/$shortcurstar" shortenedpath="$shortbegin/$end" done shortenedpath="${shortenedpath%/}" # strip trailing / shortenedpath="${shortenedpath#/}" # strip leading / echo "/$shortenedpath" # Make sure it starts with / shopt "$NGV" nullglob # Reset nullglob in case this is being used as a function.

Asígnele la longitud como primer argumento y la ruta como segundo argumento opcional. Si no se da un segundo argumento, utiliza el directorio de trabajo actual.

Esto tratará de acortar a la longitud dada. Si eso no es posible, solo da el camino más corto que puede dar.

Hablando algorítmicamente, esto es probablemente horrible, pero termina siendo bastante rápido. (La clave para los scripts de shell rápidos es evitar las subshells y los comandos externos, especialmente en los bucles internos).

Por diseño, solo se reduce en 2 o más caracteres (''hom *'' es igual a tantos caracteres como ''home'').

No es perfecto Hay algunas situaciones en las que no se acortará tanto como sea posible, como si hay varios archivos cuyos nombres de archivo comparten un prefijo (si existen foobar1 y foobar2, no se acortará foobar3).


Hice algunas mejoras al código de Evan Krall. Ahora verifica si su ruta comienza en $ HOME y comienza la variedad reducida con ~ / en lugar de / h * / u * /

#!/bin/bash begin="" # The unshortened beginning of the path. shortbegin="" # The shortened beginning of the path. current="" # The section of the path we''re currently working on. end="${2:-$(pwd)}/" # The unmodified rest of the path. if [[ "$end" =~ "$HOME" ]]; then INHOME=1 end="${end#$HOME}" #strip /home/username from start of string begin="$HOME" #start expansion from the right spot else INHOME=0 fi end="${end#/}" # Strip the first / shortenedpath="$end" # The whole path, to check the length. maxlength="${1:-0}" shopt -q nullglob && NGV="-s" || NGV="-u" # Store the value for later. shopt -s nullglob # Without this, anything that doesn''t exist in the filesystem turns into */*/*/... while [[ "$end" ]] && (( ${#shortenedpath} > maxlength )) do current="${end%%/*}" # everything before the first / end="${end#*/}" # everything after the first / shortcur="$current" shortcurstar="$current" # No star if we don''t shorten it. for ((i=${#current}-2; i>=0; i--)); do subcurrent="${current:0:i}" matching=("$begin/$subcurrent"*) # Array of all files that start with $subcurrent. (( ${#matching[*]} != 1 )) && break # Stop shortening if more than one file matches. shortcur="$subcurrent" shortcurstar="$subcurrent*" done #advance begin="$begin/$current" shortbegin="$shortbegin/$shortcurstar" shortenedpath="$shortbegin/$end" done shortenedpath="${shortenedpath%/}" # strip trailing / shortenedpath="${shortenedpath#/}" # strip leading / if [ $INHOME -eq 1 ]; then echo "~/$shortenedpath" #make sure it starts with ~/ else echo "/$shortenedpath" # Make sure it starts with / fi shopt "$NGV" nullglob # Reset nullglob in case this is being used as a function.

Además, aquí hay algunas funciones que puse en mi archivo .bashrc para reducir la ruta que muestra el shell. No estoy seguro de si editar $ PWD de esta manera sea completamente seguro ya que algunos scripts podrían depender de una cadena de $ PWD válida, pero hasta ahora no he tenido problemas con el uso ocasional. Tenga en cuenta que guardé el script anterior como "shortdir" y lo puse en mi PATH.

function tinypwd(){ PWD=`shortdir` } function hugepwd(){ PWD=`pwd` }

EDITAR 19 de octubre de 2010

La forma correcta de hacer los alias en bash es modificando la variable $PS1 ; Así es como se analiza el indicador. En la mayoría de los casos (el 99% del tiempo) la ruta actual está en la cadena de solicitud como "/ w". Podemos usar sed para reemplazar esto con shortdir , así:

#NOTE: trailing space before the closing double-quote (") is a must!! function tinypwd(){ PS1="$(echo $PS1 | sed ''s///w//`shortdir/`/g'') " } function hugepwd(){ PS1="$(echo $PS1 | sed ''s/[`]shortdir[`]///w/g'') " }


No da el mismo resultado, pero mi ~/.bashrc contiene

_PS1 () { local PRE= NAME="$1" LENGTH="$2"; [[ "$NAME" != "${NAME#$HOME/}" || -z "${NAME#$HOME}" ]] && PRE+=''~'' NAME="${NAME#$HOME}" LENGTH=$[LENGTH-1]; ((${#NAME}>$LENGTH)) && NAME="/...${NAME:$[${#NAME}-LENGTH+4]}"; echo "$PRE$NAME" } PS1=''/u@/h:$(_PS1 "$PWD" 20)/$ ''

lo que limita la ruta mostrada a 20 caracteres max. Si la ruta tiene más de 20 caracteres, se mostrará como /...d/like/shortened o ~/.../like/shortened /...d/like/shortened .


Para su información, hay un /w "acortador" incorporado en Bash 4+:

PROMPT_DIRTRIM=3

acortará /var/lib/whatever/foo/bar/baz a .../foo/bar/baz .


Prueba esto:

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

Se transforma

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

a

.vim/bund…im/plugin

transferencia de

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

a

/usr/shar…utils-7.5

Y cuando $PWD igual a $HOME , no muestres nada.

Bonificación: puede modificar el número de longitud para que se ajuste a sus necesidades.