Variádico

Mejora tus bash scripts

7 de mayo de 2016

Últimamente he estado escribiendo muchísimo Bash. No me agrada escribirlo, pero muchas veces es más fácil y más rápido escribir unas cuantas líneas de Bash en lugar de escribir algo en Python o Go. Además casi es garantizado que cualquier computador va a tener Bash instalado. A continuación les dejo unos consejos para escribir mejores bash scripts.

Usa un shebang más portátil

Este es el típico shebang para Bash.

#!/bin/bash

El problema con ese shebang es que puede causar problemas inesperados si ejecutas el script en diferentes sistemas operativos o si quieres usar un bash que no esté instalado en /bin/bash.

Por ejemplo, en OS X el bash de fabrica está en /bin/bash, pero yo uso un Bash más actualizado que está en /usr/local/bin/bash. ¿Cómo le hago para no jarcodear un Bash?

Mejor usa éste shebang.

#!/usr/bin/env bash

Así tus scripts van a ejecutarse con va versión de bash que se esté usando en tu entorno.

Configura un modo más estricto

Para una terminal, bash funciona bien. Es muy tolerante y casi no pasa nada si hay algún error con tus comandos. Por ejemplo, si escribes clera en lugar de clear el proceso bash no lanza un excepción ni cierra la ventana.

Sin embargo, al escribir código fuente, queremos lo opuesto. Muchas veces, si la primera línea falla, no queremos seguir ejecutando el código restante.

Así puedes ponerte en un modo más restrictivo.

set -euo pipefail

La línea anterior es una combinación de las siguientes opciones.

Usa shellcheck

shellcheck es una herramienta esencial. Puede verificar sintaxis, pero también detecta errores comunes.

Por ejemplo, supone que quieres encontrar la palabra “hola”, seguida por lo que sea. Quizá escribas algo así.

grep "hola*" datos.txt

Pero, si pasas tu programa por shellcheck, te darás cuenta de un error.

In bash.sh line 3:
grep "hola*" datos.txt
     ^-- SC2022: Note that unlike globs, a* here matches 'aaa' but not 'alpha'.

A diferencia de la terminal, aquí la * encuentra aaa, pero no alpha. Esto es porque grep toma una expresión regular, no un glob. En ambito de expresiones regulares, * quiere decir, «cero o más del carácter anterior».

Muy largo; no leí

Si no tienes requisitos específicos, empieza todos tus scripts así.

#!/usr/bin/env bash
set -euo pipefail

También, usa shellcheck para verificar tus scripts.

# OS X
brew install shellcheck
# Debian
sudo apt-get install shellcheck