Curso de Shell Scripting
Muchos scripts en realidad se ejecutan con /bin/sh (el shell estándar POSIX), que no siempre es Bash.
El problema es que a menudo escribimos “Bashisms”: funciones o sintaxis que solo funcionan en Bash y rompen el script en otros shells.
18.1. POSIX vs Bash
- POSIX sh: estándar compatible con la mayoría de sistemas (mínimo común).
- Bash: incluye muchas extensiones que no están en POSIX.
👉 Si tu script declara en la primera línea:
1#!/bin/sh
… deberías escribir solo sintaxis POSIX, no características propias de Bash.
👉 Si usas extensiones de Bash (arrays, [[ ]], brace expansion, etc.), declara explícitamente:
1#!/usr/bin/env bash
18.2. Identificar Bashisms
Usa checkbashisms para encontrar código no POSIX:
En Debian/Ubuntu:
1sudo apt install devscripts 2checkbashisms script.sh
Ejemplo de salida:
possible bashism in script.sh line 3 (double brackets [[ ]])
👉 Esto te dice qué partes romperán en /bin/sh.
18.3. Pruebas rápidas con otros shells
Ejecuta el script con dash (un shell POSIX rápido y estricto):
1dash script.sh
👉 Si falla, probablemente contiene Bashisms.
18.4. Bashisms comunes a evitar (si necesitas POSIX)
| Bashism | POSIX equivalente |
|---|---|
[[ ... ]] | [ ... ] o test ... |
function foo {} | foo() { ... } |
Arrays arr=(a b c) | Usa variables separadas o archivos |
((a+b)) | Usa expr o $((a+b)) solo si es soportado |
echo {1..5} | Usa bucles for i in 1 2 3 4 5 |
source archivo | Usa . archivo |
declare o local | Usa variables simples o export |
Ejemplo no portátil:
1#!/bin/sh 2for i in {1..5}; do 3 echo $i 4done
👉 Falla en dash.
✅ Solución POSIX:
1#!/bin/sh 2for i in 1 2 3 4 5; do 3 echo "$i" 4done
18.5. Portabilidad en expresiones condicionales
Malo (Bash):
1if [[ "$VAR" == "hola" ]]; then 2 echo "ok" 3fi
✅ Portátil (POSIX):
1if [ "$VAR" = "hola" ]; then 2 echo "ok" 3fi
18.6. Portabilidad en sustituciones de comandos
Malo:
1VAL=$(<archivo.txt)
👉 Algunos shells antiguos no soportan esa forma.
✅ Portátil:
1VAL=$(cat archivo.txt)
18.7. Portabilidad en variables
Malo (Bash):
1VAR=${OTRA:-default}
👉 La expansión ${VAR:-valor} está disponible en Bash y en shells POSIX modernos, pero no en algunos antiguos.
⚠️ Si apuntas a sistemas muy viejos, evita expansiones complejas y usa condiciones tradicionales.
18.8. Portabilidad en bucles con read
Malo (Bash con opciones avanzadas):
1while IFS= read -r -d '' line; do 2 echo "$line" 3done < archivo.txt
✅ Más portátil:
1while IFS= read line 2do 3 echo "$line" 4done < archivo.txt
18.9. Buenas prácticas para scripts portables
- ✅ Usa
#!/bin/shsolo si el script es POSIX puro. - ✅ Usa
#!/usr/bin/env bashsi dependes de características de Bash. - ✅ Prueba con
dashycheckbashismspara detectar problemas. - ✅ Evita
[[ ]], arrays, brace expansion,source. - ✅ Usa solo comandos estándar:
echo,printf,test,grep,awk,sed,cut,sort. - ✅ Evita rutas absolutas si no son necesarias o hazlas configurables.
- ✅ Documenta las dependencias externas (por ejemplo,
curl,jq).
18.10. Ejemplo integrador: script portátil
1#!/bin/sh 2# script_portable.sh 3 4if [ $# -ne 1 ]; then 5 echo "Uso: $0 archivo" 6 exit 1 7fi 8 9ARCHIVO="$1" 10 11if [ ! -f "$ARCHIVO" ]; then 12 echo "Error: no existe el archivo $ARCHIVO" 13 exit 1 14fi 15 16LINEAS=$(wc -l < "$ARCHIVO") 17echo "El archivo tiene $LINEAS líneas"
👉 Compatible con Bash, Dash y la mayoría de shells POSIX.
🏋️♂️ Ejercicio práctico 1
Crea un script contar_palabras.sh que:
- Sea 100% POSIX (usa
#!/bin/sh). - Acepte un archivo como argumento.
- Compruebe que el archivo existe.
- Muestre el número de palabras con
wc -w.
Prueba que funciona tanto con bash como con dash.
🏋️♂️ Ejercicio práctico 2
Crea un script saludar.sh que:
-
Sea portátil y compatible con
/bin/sh. -
Acepte un nombre como argumento.
-
Si no se pasa argumento, muestre:
Uso: ./saludar.sh <nombre> -
Si recibe argumento, muestre:
Hola, <nombre>
🏋️♂️ Ejercicio práctico 3
Crea un script procesa_archivos.sh que:
- Sea POSIX puro.
- Procese todos los archivos
*.txtdel directorio actual. - Muestre el nombre y número de líneas de cada archivo.
- Use solo comandos POSIX (
for,wc,echo).
✅ Buenas prácticas finales
- ✅ Decide desde el inicio: ¿tu script será POSIX (máxima portabilidad) o Bash (más moderno y potente)?
- ✅ Declara el intérprete correcto en la shebang (
#!/bin/sho#!/usr/bin/env bash). - ✅ Usa herramientas como
checkbashismsy pruebas condashpara garantizar portabilidad. - ✅ Documenta los requisitos (por ejemplo: “Requiere Bash ≥4.0” o “Compatible con POSIX”).
- Loading...