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ísticaZshFish
ConfiguraciónNecesita personalización, pero muy flexible. Usa .zshrc para configuración.Viene con configuración predeterminada útil. Usa config.fish.
Compatibilidad con BashAlta compatibilidad con Bash, puede ejecutar scripts Bash sin cambios.No es compatible con Bash, su sintaxis es diferente.
AutosugerenciasSí, pero requiere plugins (por ejemplo, zsh-autosuggestions).Sí, integrado por defecto.
Completado de comandosNecesita complementos como oh-my-zsh.Completado avanzado e interactivo de fábrica.
Sintaxis de variablesSimilar a Bash ($VAR).Usa set VAR valor en lugar de VAR=valor.
Funciones y scriptingSimilar 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ónZshFish
    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ónZshFish
    Ejecución de un comando simple (ls)RápidoRápido
    Expansión de variables grandesSimilar a Bash (rápido)Puede ser más lento si hay muchas variables globales
    AutocompletadoDepende de los pluginsMá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)ZshFish
    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.

    EscenarioZshFish
    Ejecutar scripts Bash nativosCompatibleNo compatible
    Manejo de grandes cantidades de datos en scriptsEficienteMá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 interactivaFish es más rápido y más intuitivo. Si quieres compatibilidad, menor consumo de RAM y mejor desempeño en scriptsZsh 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.

    ← Volver a los artículos