Por qué elegir Fish o ZSH: Ventajas y Desventajas
Normalmente nos encontramos en GNU/Linux y otros sistemas *Nix, que el shell por defecto es Bash. Bash es muy potente, pero desde hace años se me antoja obsoleto por la falta de personalización y características. Así que en su momento lo reemplacé por ZSH.
Incluso Apple decidió hace un par de años cambiar Bash por ZSH en macOS, con lo cual fue todo más fácil para mi en su momento. Eso si, ZSH por si solo no es la gran cosa, pero una vez que le pones plugins, temas y demás, todo cambia.
Es muy popular el hacer uso de OhMyZSH un framework para potencias ZSH de mano de la comunidad que tienes que instalar SI o SI, si usas este Shell. Y por años ZSH ha sido mi elección. Pero hace unos días instalé CachyOS para probar, y esta distribución viene por defecto con otro shell llamado Fish.
Fish ya incluye un montón de funcionalidades por defecto que hay que añadir en ZSH como plugins. Además, la forma del autocompletado, los colores, y otro montón de detalles, lo hacen extremadamente adictivo y atractivo. Pero no es perfecto, y su enfoque "user friendly" hace que cambie algunas cosas a las que estamos acostumbrados con Bash o ZSH.
Veamos algunos ejemplos cortesía de la Inteligencia Artificial, que me ahorró el trabajo de escribir todo esto.
Diferencias Generales
| Característica | Zsh | Fish |
|---|---|---|
| Configuración | Necesita personalización, pero muy flexible. Usa .zshrc para configuración. | Viene con configuración predeterminada útil. Usa config.fish. |
| Compatibilidad con Bash | Alta compatibilidad con Bash, puede ejecutar scripts Bash sin cambios. | No es compatible con Bash, su sintaxis es diferente. |
| Autosugerencias | Sí, pero requiere plugins (por ejemplo, zsh-autosuggestions). | Sí, integrado por defecto. |
| Completado de comandos | Necesita complementos como oh-my-zsh. | Completado avanzado e interactivo de fábrica. |
| Sintaxis de variables | Similar a Bash ($VAR). | Usa set VAR valor en lugar de VAR=valor. |
| Funciones y scripting | Similar a Bash. | Tiene su propia sintaxis para funciones y scripts. |
Diferencias en Uso y Scripting
(a) Declaración de Variables
En Zsh (similar a Bash):
zsh VAR="Hola mundo"
echo $VAR
En Fish (diferente sintaxis):
fish set VAR "Hola mundo"
echo $VAR
Zsh usa VAR=valor, mientras que Fish usa set VAR valor.
(b) Uso de Variables en Comandos
En Zsh:
zsh NAME="Carlos"
echo "Hola $NAME"
En Fish, el uso de variables en cadenas es diferente:
fish set NAME "Carlos"
echo "Hola $NAME"
(c) Exportar Variables de Entorno
En Zsh:
zsh export PATH=$PATH:/nuevo/directorio
En Fish:
fish set -x PATH $PATH /nuevo/directorio
set -x se usa para hacer que una variable esté disponible en procesos hijos.
(d) Definir Funciones
En Zsh:
zsh mi_funcion() {
echo "Hola desde Zsh"
}
mi_funcion
En Fish:
fish function mi_funcion
echo "Hola desde Fish"
end
mi_funcion
Fish usa function nombre y cierra con end.
(e) Alias y Atajos
En Zsh:
alias ll="ls -l"
En Fish:
alias ll "ls -l"
Fish no usa = para los alias.
(f) Scripts
Un script en Zsh (y compatible con Bash):
zsh#!/bin/zsh
echo "Este es un script en Zsh"
VAR="Ejemplo"
echo "Variable: $VAR"
Un script en Fish (requiere su propia sintaxis):
fish#!/usr/bin/env fish
echo "Este es un script en Fish"
set VAR "Ejemplo"
echo "Variable: $VAR"
Fish no usa #!/bin/fish de forma obligatoria, pero es recomendable.
Expansión de Parámetros
Zsh permite expansión avanzada como en Bash:
files=(*) # Lista de archivos en el directorio
echo ${files[1]} # Primer archivo
En Fish, no hay arrays como en Bash/Zsh. Se usa una lista separada por espacios:
set files (ls)
echo $files[1] # Primer archivo
Diferencia: Zsh usa índices 1-based por defecto, pero Fish los maneja de manera similar a Bash.
Manejo de Alias Avanzado
Zsh permite alias con argumentos:
alias ll='ls -l'
alias grep='grep --color=auto'
Fish usa alias sin = y no permite argumentos dentro del alias:
alias ll "ls -l"
Para alias más avanzados en Fish, necesitas funciones:
function grep
command grep --color=auto $argv
end
Diferencia: Fish no admite alias con argumentos, debes usar funciones.
Diferencias en Redirección de Salida
Zsh permite redirección avanzada:
echo "Hola" > archivo.txt # Escribe en el archivo
echo "Mundo" >> archivo.txt # Agrega al archivo
En Fish, la redirección es similar, pero con diferencias en stderr:
echo "Hola" > archivo.txt
echo "Mundo" >> archivo.txt
Para capturar stderr en Zsh:
comando 2> error.log
En Fish:
comando ^ error.log
Diferencia: Fish usa ^ en lugar de 2> para redirigir stderr.
Expansión de Variables en Comillas
En Zsh, puedes hacer expansión dentro de comillas dobles:
NAME="Carlos"
echo "Hola, $NAME"
En Fish:
set NAME "Carlos"
echo "Hola, $NAME"
Pero si usas comillas simples en Fish, no expande la variable:
echo 'Hola, $NAME' # Mostrará $NAME literal
Diferencia: Fish no expande variables dentro de comillas simples.
Uso de Subprocesos ($() vs ())
En Zsh:
current_dir=$(pwd)
echo "Estoy en $current_dir"
En Fish:
set current_dir (pwd)
echo "Estoy en $current_dir"
Diferencia: Fish usa () en lugar de $() para capturar salida de comandos.
Expansión de Rutas y Globbing
En Zsh, puedes expandir rutas con **:
ls */.txt # Encuentra todos los archivos .txt en subdirectorios
En Fish:
ls */.txt
Ambos admiten **, pero Fish lo activa de fábrica mientras que en Zsh a veces necesitas:
setopt globstar
Diferencia: En Fish, ** funciona siempre; en Zsh puede requerir configuración extra.
Completado de Comandos
En Zsh, debes instalar oh-my-zsh o plugins como zsh-autosuggestions:
Activar autocompletado en Zsh
autoload -U compinit
compinit
En Fish, el autocompletado avanzado está integrado de fábrica.
Diferencia: Fish tiene autocompletado avanzado sin necesidad de plugins.
Trabajar con Listas
En Zsh:
lista=(uno dos tres)
echo ${lista[2]} # Muestra "dos"
En Fish:
set lista uno dos tres
echo $lista[2] # Muestra "dos"
Diferencia: Fish trata listas como variables con múltiples valores.
Uso de Historia del Comando (!! vs history)
En Zsh:
echo "Hola" # Ejecutamos un comando
!! # Repite el último comando
En Fish, no existe !!, debes hacer:
echo "Hola"
history | tail -n 1 | source
Diferencia: Fish no usa !!, pero su historial es más avanzado.
Iterar sobre Archivos
En Zsh:
for file in *.txt; do
echo "Archivo: $file"
done
En Fish:
for file in *.txt
echo "Archivo: $file"
end
Diferencia: Fish usa end en lugar de done.
Tiempos de inicio del Shell
Fish generalmente inicia más rápido que Zsh, especialmente si Zsh tiene muchos plugins o una configuración compleja.
| Medición | Zsh | Fish |
|---|---|---|
| Tiempo de inicio (sin plugins) | 15-30 ms | ~10 ms |
| Tiempo de inicio (con plugins y configuración compleja) | Puede superar los 100 ms | ~20-30 ms (depende de las funciones añadidas) |
➡ Conclusión:
- Fish es más rápido de inicio, porque viene optimizado de fábrica.
- Zsh puede ralentizarse con plugins como
oh-my-zsh, pero bien optimizado sigue siendo ágil.
Ejemplo para medir tiempos
Si quieres medir el tiempo que tarda en iniciarse cada shell:
Desde ZSH estos fueron los tiempos ejecutados:
elav@beemini ~> time zsh -i -c exit
zsh -i -c exit 0.04s user 0.06s system 111% cpu 0.089 total
elav@beemini ~> time fish -i -c exit
fish -i -c exit 0.00s user 0.00s system 90% cpu 0.007 total
Desde Fish estos fueron los tiempos ejecutados:
elav@beemini ~> time zsh -i -c exit
________________________________________________________
Executed in 84.91 millis fish external
usr time 39.93 millis 302.00 micros 39.63 millis
sys time 55.87 millis 306.00 micros 55.56 millis
elav@beemini ~> time fish -i -c exit
________________________________________________________
Executed in 6.35 millis fish external
usr time 2.10 millis 276.00 micros 1.82 millis
sys time 3.89 millis 270.00 micros 3.62 millis
Incluso como se puede ver, Fish muestra una salida mucho más fácil de visualizar. Pero como sea, Fish parece ser ligeramente más rápido en todo.
Ejecución de Comandos
La ejecución de comandos es similar en ambos shells, ya que dependen más del sistema operativo que del propio shell. Sin embargo:
| Acción | Zsh | Fish |
|---|---|---|
Ejecución de un comando simple (ls) | Rápido | Rápido |
| Expansión de variables grandes | Similar a Bash (rápido) | Puede ser más lento si hay muchas variables globales |
| Autocompletado | Depende de los plugins | Más rápido porque está integrado de fábrica |
➡ Conclusión:
- Fish puede ser más lento con muchas variables de entorno, ya que usa un sistema interno diferente.
- Zsh puede volverse más lento con configuraciones pesadas, pero optimizable.
Uso de Memoria RAM
Fish usa más memoria que Zsh porque mantiene estructuras de datos avanzadas para su autocompletado y sugerencias.
| Consumo de RAM (estimado) | Zsh | Fish |
|---|---|---|
| Sin configuración extra | ~2-4 MB | ~5-10 MB |
| Con configuración avanzada | ~10-15 MB (con muchos plugins) | ~15-20 MB (por su sistema de variables) |
➡ Conclusión:
- Si tienes poca RAM o un sistema muy limitado, Zsh puede ser una mejor opción.
- Fish usa más memoria, pero sigue siendo ligero en comparación con aplicaciones pesadas.
Escalabilidad en Scripts y Automatización
Zsh es mejor en automatización y scripting porque es más compatible con Bash.
| Escenario | Zsh | Fish |
|---|---|---|
| Ejecutar scripts Bash nativos | Compatible | No compatible |
| Manejo de grandes cantidades de datos en scripts | Eficiente | Más lento si usa muchas variables globales |
➡ Conclusión:
- Zsh es mejor para scripts y uso en entornos empresariales o automatización.
- Fish es más eficiente en uso interactivo, pero no está diseñado para scripting complejo.
Veredicto Final
Si buscas rapidez en inicio y una mejor experiencia interactiva → Fish es más rápido y más intuitivo. Si quieres compatibilidad, menor consumo de RAM y mejor desempeño en scripts → Zsh es más eficiente en general.
Si usas tu shell para administrar sistemas y ejecutar scripts, Zsh es mejor opción. Si solo buscas un shell interactivo rápido y fácil de usar, Fish es una gran elección.
- Si quieres compatibilidad con Bash y un shell potente con plugins → Usa Zsh.
- Si prefieres un shell más intuitivo y listo para usar sin configurar → Usa Fish.
Si trabajas con muchos scripts, Zsh es mejor opción debido a su compatibilidad con Bash. Si solo usas el terminal de forma interactiva y quieres comodidad sin configurar nada, Fish es una gran elección.
Pero aquí aplica el meme: ¿Por qué no ambos? Ambos es bueno..
Y es que lo bueno que tenemos al usar un terminal, es que podemos establecer por defecto un Shell cualquiera, y ejecutar otro simplemente llamándolo. Así que mejor nos instalamos todos y usamos el que queramos según el contexto.