El operador "!" en BASH: ejecutar comandos del historial sin tener que buscar/copiar/pegar.
Origen de este artículo.
Estaba trabajando en la terminal, ejecuté "history | grep /usr/" y obtuve una lista de comandos anteriores con sus IDs. Me pregunté por primera vez si era posible ejecutar el comando número "475" sin tener que copiarlo manualmente, reescribirlo o buscarlo con flechas arriba/abajo interminablemente (como hago casi siempre, por comodidad).
La solución está en el operador "!", pero su sintaxis no es para nada intuitiva: al contrario, confunde, porque históricamente significa "negación". Dicho sea de paso... ¿a quién se le ocurrió usar ese símbolo y no otro más apropiado? Rarezas del "si pasa, pasa", del mundo de la programación.
¿Qué es "!"?
"!", es el operador de expansión de historial en BASH. Permite referenciar y ejecutar comandos previos de múltiples formas. Viene heredado de shells antiguos (csh, tcsh) y su diseño prioriza brevedad sobre claridad.
Varios ejemplos para su utilización.
1. Ejecución por número de ID.
!475
esto ejecuta directamente el comando que está en la línea 475 del historial:
history | grep /usr/
430 sudo cp /home/entropia/conf/Commodore_64-Pantalla_BN.png /usr/share/backgrounds/
475 ls -l /usr/share/backgrounds/
499 history | grep /usr/
Al tipear "!475" [Enter], el resultado será la ejecución de "ls -l /usr/share/backgrounds/" inmediatamente.
2. Ejecución del "último comando".
Ejecutar "!!", repite el último comando ejecutado. Puede ser útil cuando olvidaste poner "sudo" delante de la orden, cosa que me pasa a menudo.
En este caso, estoy intentando ejecutar GParted, herramienta que necesida privilegios de root debido a las tareas que resuelve:
gparted
Root privileges are required for running gparted.
GParted 1.8.0
configuration --enable-libparted-dmraid
libparted 3.6
Se requieren privilegios de root para ejecutar GParted
Entonces, como olvidé poner "sudo", ahora hago esto, y mirá la diferencia:
[entropia@void-entropia ~]$ sudo !!
sudo gparted
Contraseña:
El "sudo gparted" lo devolvió la terminal: no tuve que ponerlo yo.
Imaginate olvidar "sudo" en una línea sumamente extensa... el tiempo que ahorra es de importancia.
3. Ejecución del comando anterior que empezaba con "cierta palabra".
!ls
Ejecuta el comando más reciente que empezó con "ls".
!sudo
Ejecuta el comando más reciente que empezó con "sudo".
4. Previsualización previa a la ejecución.
!475:p
El modificador ":p" (print) muestra el comando sin ejecutarlo. Luego, aparece en el historial y podés presionar [↑][Enter] para ejecutarlo si es el correcto.
Ejemplo basado en mi caso.
- Tipeás "!475:p"...
- Se muestra "ls -l /usr/share/backgrounds/"
- Pulsás [↑]
- Aparece "ls -l /usr/share/backgrounds/"
- Presionás [Enter] para ejecutar esa orden.
5. Buscar por contenido (pero no solo "al inicio").
!?backgrounds
Ejecuta el comando más reciente que contenga a la palabra "backgrounds" en cualquier parte.
!?/usr/
ejecuta el comando más reciente que contenga "/usr/" en cualquier lugar de la orden.
6. referencia a argumentos del último comando.
Supongamos que "hace un rato" hemos hecho "ls /usr/share/backgrounds/" y ahora queremos copiar algo allí. Entonces, podemos hacer esto:
cp Imagen.png !$
¿Por qué?
Porque "!$", expande el último argumento del comando anterior.
El resultado, sería, entonces: "cp imagen.png /usr/share/backgrounds/"
7. "Bonus track".
Te dejo otros modificadores de argumentos (ya no tan explicados) para que busques más información si te interesó esto de BASH, lo cual espero que así haya sido.
No sigo detallando porque se haría interminable el artículo, y además, porque si esto que te expliqué antes ya era algo inusual, lo que te comentaré a continuación, lo será aún más.
!$ : último argumento del comando anterior.
!^ : primer argumento del comando anterior.
!* : todos los argumentos del comando anterior.
!-2 : ejecutar el comando que está 2 posiciones atrás en el historial.
!-1 : equivale a "!!" (el comando inmediatamente anterior).
ls /usr/share/backgrounds/
# Como te equivocaste de directorio, entonces...
^backgrounds^fonts
# Ejecuta: ls /usr/share/fonts/
8. "Bonus subtrack."
¿Sabés que se puede editar el archivo ".bashrc" con finalidades bien interesantes?
Por ejemplo, para evitar duplicados en el historial:
HISTCONTROL=ignoredups:erasedups
Reflexión final.
El operador "!" no es intuitivo hoy, porque, entre otras cosas, viene de una época en donde la brevedad era crítica. Pero una vez que entiendas su lógica
! + número : ejecutar por ID
! + palabra : ejecutar por inicio
!? + palabra : ejecutar por contenido
comprenderás que es una herramienta poderosa para evitar copiar/pegar y trabajar más eficientemente en terminal y consola.

0 Comentarios:
Publicar un comentario