Tu propia biblioteca de comandos en Bash

El historial de bash recoge montones de comandos complejos que lleva su rato concebirlos, diseñarlos, ajustarlos (al menos es mi caso). Buscando por recursos compartidos por otr_s, para mejorar mi experiencia con bash y compartirla con ustedes, encontré en un par de ajustes sencillos que me ayudan a conservar un historial más largo, y una forma de definir una función personalizada de bash para hacer aún más fácil mis búsquedas por el historial.

Inicialmente, en el archivo que configura mi sesión de bash al iniciar sesión (~/.bashrc para mí, pero podría ser ~/.bash_profiles para otros) ajusté la configuración de 3 líneas:


export HISTCONTROL=erasedups
export HISTSIZE=10000
shopt -s histappend

Y ahora trato de explicarlo.

La primera elimina duplicados del historial, cuando se añade un nuevo elemento. Por ejemplo si cambias entre make y ./a.out en la shell, podrías después encontrar que las últimas decenas de comandos, es una mezcla de estos dos comandos, y pues no resulta muy útil.

La segunda hace más grande el tamaño del historial, con los duplicados fuera, ya tenemos información más selecta, pero todavía me gustaría que guarde más que sólo 1,000 elementos.

La tercera asegura que cuando sales de una terminal, el historial de esa sesión se añade a ~/.bash_history. Sin esto, se perdería la información de sesiones enteras (sería raro que esto no estuviera habilitado por defecto).

‘Hurgando’ en el Historial

Pero guardar el historial es sólo el inicio de la diversión, podemos jugar de varias formas con ello.

Con GREP

La más básica, con ella puedes hacer algo como:


history | grep "watch"

# 'history' y nomás, me devolvería el historial completo, podría verlo
# página por página con less. Pero con grep puedo filtar lo que me
# interesa en realidad, en este caso los 'watch' con que supervisé en
# algún momento el progreso de algún trabajo normalmente 'silencioso'

Aquí tenemos una salida de ejemplo:

    8  watch -n5 tail wget-log
  111  watch -n6 transmission-remote -l
  191  watch -n3 -d 'transmission-remote -l | cut -b2-22,36-42,45-'
  433  watch -n8 -d 'transmission-remote -l | cut -b2-22,36-42,45-63,70-100'

Explicar tales comandos rebasa la intención de este post, pero es justo el que sigue😉

De la salida puedo copiar/pegar lo que me sirva, o repetir una entrada precisa, como cada una está numerada, puedes repetir simplemente, digamos la 433:

!433

Si encuentras esto útil podrías tener un alias en .bashrc o .bash_aliases para ahorrarte tipeo:

alias h='history | grep'

Entonces ya sólo tendrías que escribir

h "regexp filtro"

Sin embargo sólo escribiendo h, fallará porque este alias espera un argumento para grep, pero a continuación vemos un mejor modo de evitarnos quebraderos de cabeza

Artículo original

Definiendo una función en .bashrc

Este ejemplo me pareció interesante también porque nos presenta de modo sencillo como definir funciones personalizadas en nuestro propio entorno de bash.


function h() {
if [ -z "$1" ]
then
history
else
history | grep "$@"
fi
}

Explicación

* Líneas 2 a 4: Si el usuario llama el comando h sin argumentos, la función invoca el comando history ‘a secas’.
* Líneas 5 a 7: De otro modo, invoca ‘history’ y lo filtra con grep con el argumento que deseamos.

Artículo original

Búsqueda incremental

Quien está acostumbrado a los navegadores modernos sabrá a que me refiero, vas escribiendo tu búsqueda y va saltando a la primera ocurrencia de esa cadena, fallando si nada coincide, es lo que llamamos ‘incremental’.

Como no estamos ‘en mitad de un documento’ la búsqueda hacia delante no tiene sentido, así que sólo tenemos ‘en reversa’: el atajo es lógico: Control-R (o C-r en notación de Emacs).

La verdad es que lo más divertido es probarlo: presionas C-r, empiezas a escribir y se va mostrando con cada nuevo caracter, la última línea donde apareció esa cadena, pero puedes ir a las previas presionando subsecuentemente C-r. Si sales de una búsqueda mediante C-c, puedes volver a tu búsqueda previa repitiendo C-r (la primera vez te permite una nueva búsqueda, la segunda asume que quieres seguir hurgando con la cadena pasada).


Expansión de Historial

¡Más potencia, más potencia!
tzk en modo-tim-allen😄

Cuando anteriormente vimos que !número invoca el último comando, no explicamos que además podemos editar esa entrada para usarla en un nuevo comando. Es tan simple como presionar Alt-Ctrl-e (M-C-e) antes de presionar Enter y disparar el comando sin editar. Entonces aparece el evento que habíamos especificado, y podemos editarlo normalmente, ya aquí hay una obscena cantidad de atajos para no tener que borrar y teclear de nuevo comandos enteros (no estamos en DOS ¿recuerdas?):

Recuerda, C- es Ctrl- y M- es Alt-

M-r    Deshace todos los cambios.
C-_    Deshace el último cambio.
C-a    Regresa al principio de la línea (above)
C-e    Va al final (end) de la línea.
C-b    Hacia atrás  (back) un caracter. A veces no funcionan
       las flechas del teclado con ciertas terminales.
M-f    Hacia atrás una palabra.
C-f    Hacia delante un caracter.
M-f    Hacia delante una palabra.
C-u    Borra del cursor al principio de la línea.
C-k    Borra del cursos al final de la línea.
C-y    Pega texto del portapapeles.
C-l    Borra la pantalla (¿pa'qué escribir clear?)

Pero podemos {invocar,substituir} partes de entradas previas con más atajos:

!!      Ejecuta el último comando.
!str    Ejecuta el último comando con la cadena dada.
!str:p  Sólo lo muestra (prints), no lo ejecuta. 

Tomando partes de argumentos previos.

!^      El primer argumento del comando anterior.
!$      El último argumento del comando anterior.

Substituyendo (como haciendo sed -e ‘s:esto:por esto:’)

^orig^subst     Reemplaza la primer ocurrencia de orig,
                la substituye por subst, y ejecuta el
                comando modificado.

Espero te diviertas más con el historial de ahora en adelante.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s