Fish - Shell Interactivo Amigable¶
Fish (Friendly Interactive Shell) es un shell de línea de comandos inteligente y amigable diseñado para uso interactivo, usabilidad y descubrimiento. Creado por Axel Liljencrantz en 2005, Fish toma un enfoque diferente de los shells tradicionales al priorizar la experiencia de usuario y proporcionar configuraciones predeterminadas sensatas de inmediato. A diferencia de los shells compatibles con POSIX, Fish cuenta con resaltado de sintaxis, autosugerencias, completaciones de pestaña que funcionan sin configuración, y una sintaxis limpia y moderna que busca ser más intuitiva y menos propensa a errores que los lenguajes de shell tradicionales.
Instalación y Configuración¶
Instalando Fish Shell¶
# Ubuntu/Debian
sudo apt update && sudo apt install fish
# CentOS/RHEL/Fedora
sudo dnf install fish
# macOS (using Homebrew)
brew install fish
# Arch Linux
sudo pacman -S fish
# FreeBSD
pkg install fish
# From source (latest version)
git clone https://github.com/fish-shell/fish-shell.git
cd fish-shell
cmake .
make
sudo make install
Configurando Fish como Shell Predeterminado¶
# Check Fish installation
which fish
/usr/bin/fish
# Add Fish to available shells
echo /usr/bin/fish|sudo tee -a /etc/shells
# Set Fish as default shell
chsh -s /usr/bin/fish
# Verify change (restart terminal)
echo $SHELL
Configuración Inicial¶
# Start Fish shell
fish
# Fish will create configuration directory automatically
# ~/.config/fish/
# Run Fish configuration wizard
fish_config
# This opens a web-based configuration interface
# Accessible at http://localhost:8000
Estructura de Configuración Básica¶
# Fish configuration files
~/.config/fish/config.fish # Main configuration file
~/.config/fish/functions/ # Custom functions directory
~/.config/fish/completions/ # Custom completions directory
~/.config/fish/conf.d/ # Additional configuration files
# Create basic config.fish
mkdir -p ~/.config/fish
cat > ~/.config/fish/config.fish << 'EOF'
# Fish configuration
# Set environment variables
set -gx EDITOR vim
set -gx BROWSER firefox
# Add to PATH
set -gx PATH $HOME/bin $PATH
set -gx PATH $HOME/.local/bin $PATH
# Aliases
alias ll 'ls -alF'
alias la 'ls -A'
alias l 'ls -CF'
# Custom greeting
set fish_greeting "Welcome to Fish Shell!"
EOF
Sintaxis y Características del Lenguaje Fish¶
Variables y Ámbito¶
# Variable assignment (no $ for assignment)
set name "John Doe"
set age 30
set path "/home/user"
# Using variables ($ required for expansion)
echo $name
echo "Hello, $name"
echo "Age: $age"
# Variable scopes
set -l local_var "local" # Local to current scope
set -g global_var "global" # Global to current session
set -U universal_var "universal" # Universal across all sessions
set -x exported_var "exported" # Exported to child processes
# Multiple assignment
set fruits apple banana orange
echo $fruits[1] # apple (1-indexed)
echo $fruits[2] # banana
echo $fruits[-1] # orange (last element)
# Array operations
set fruits $fruits grape # Append
set fruits[2] kiwi # Replace element
set -e fruits[1] # Erase element
Sustitución de Comandos¶
# Command substitution using parentheses
set current_date (date)
set file_count (ls|wc -l)
set user_home (eval echo ~$USER)
# Nested command substitution
echo "Today is "(date +%A)", "(date +%B)" "(date +%d)
# Store command output in variable
set git_branch (git branch --show-current 2>/dev/null)
if test -n "$git_branch"
echo "Current branch: $git_branch"
end
Manipulación de Cadenas¶
# String operations
set string "Hello, World!"
echo (string length "$string") # String length
echo (string sub -s 1 -l 5 "$string") # Substring (Hello)
echo (string replace "Hello" "Hi" "$string") # Replace
echo (string upper "$string") # Uppercase
echo (string lower "$string") # Lowercase
# String splitting and joining
set words (string split " " "$string")
echo $words[1] # Hello,
set rejoined (string join "-" $words)
echo $rejoined # Hello,-World!
# Pattern matching
if string match -q "Hello*" "$string"
echo "String starts with Hello"
end
# Regular expressions
if string match -qr "W\w+d" "$string"
echo "String contains word starting with W and ending with d"
end
Declaraciones Condicionales¶
# if-then-else
if test $age -gt 18
echo "Adult"
else if test $age -eq 18
echo "Just turned adult"
else
echo "Minor"
end
# Test conditions
if test -f "file.txt" # File exists
echo "File exists"
end
if test -d "directory" # Directory exists
echo "Directory exists"
end
if test "$var" = "value" # String equality
echo "Variable equals value"
end
if test $num -eq 10 # Numeric equality
echo "Number is 10"
end
# Logical operators
if test $age -gt 18; and test $age -lt 65
echo "Working age"
end
if test $status -eq 0; or test $force = "true"
echo "Success or forced"
end
if not test -f "file.txt"
echo "File does not exist"
end
# Switch statement
switch $file_extension
case "txt"
echo "Text file"
case "jpg" "png" "gif"
echo "Image file"
case "*"
echo "Unknown file type"
end
Bucles e Iteración¶
# for loop
for i in (seq 1 10)
echo "Number: $i"
end
for file in *.txt
echo "Processing: $file"
end
for item in $array
echo "Item: $item"
end
# while loop
set counter 1
while test $counter -le 10
echo "Counter: $counter"
set counter (math $counter + 1)
end
# Loop control
for i in (seq 1 10)
if test $i -eq 5
continue # Skip iteration
end
if test $i -eq 8
break # Exit loop
end
echo $i
end
Funciones y Scripting¶
Definición de Funciones¶
# Basic function
function greet
echo "Hello, $argv[1]!"
end
# Function with description
function greet --description "Greet a user"
echo "Hello, $argv[1]!"
end
# Function with argument validation
function calculate_sum --description "Calculate sum of two numbers"
if test (count $argv) -ne 2
echo "Usage: calculate_sum <num1> <num2>"
return 1
end
math $argv[1] + $argv[2]
end
# Function with local variables
function process_file --description "Process a file"
set -l filename $argv[1]
set -l line_count (wc -l < "$filename")
echo "File $filename has $line_count lines"
end
Características Avanzadas de Funciones¶
# Function with options
function my_ls --description "Enhanced ls with options"
argparse 'l/long' 'a/all' 'h/help' -- $argv
or return
if set -q _flag_help
echo "Usage: my_ls [-l|--long] [-a|--all] [directory]"
return
end
set -l ls_args
if set -q _flag_long
set ls_args $ls_args -l
end
if set -q _flag_all
set ls_args $ls_args -a
end
ls $ls_args $argv
end
# Function with completion
function mycommand --description "Custom command with completion"
switch $argv[1]
case "start"
echo "Starting service"
case "stop"
echo "Stopping service"
case "status"
echo "Service status"
case "*"
echo "Usage: mycommand \\\\{start|stop|status\\\\}"
end
end
# Save function permanently
funcsave greet
funcsave calculate_sum
Manejo de Errores¶
# Function with error handling
function safe_copy --description "Safe file copy with error handling"
if test (count $argv) -ne 2
echo "Error: Exactly two arguments required" >&2
return 1
end
set -l source $argv[1]
set -l dest $argv[2]
if not test -f "$source"
echo "Error: Source file '$source' does not exist" >&2
return 1
end
if test -f "$dest"
echo "Warning: Destination file '$dest' already exists"
read -P "Overwrite? (y/N): " -l confirm
if test "$confirm" != "y"
echo "Copy cancelled"
return 1
end
end
if cp "$source" "$dest"
echo "Successfully copied '$source' to '$dest'"
else
echo "Error: Failed to copy file" >&2
return 1
end
end
Características Interactivas¶
Autosugerencias¶
# Autosuggestions are enabled by default
# Type a command and Fish will suggest completions based on:
# - Command history
# - Valid file paths
# - Command completions
# Accept suggestion: Right arrow or Ctrl+F
# Accept single word: Alt+Right arrow or Alt+F
# Dismiss suggestion: Escape
# Configure autosuggestion color
set -g fish_color_autosuggestion 555
Completaciones de Pestaña¶
# Tab completions work automatically for:
# - Commands in PATH
# - File and directory names
# - Command-specific options and arguments
# Custom completion for your function
complete -c mycommand -a "start stop status restart" -d "Service commands"
complete -c mycommand -s h -l help -d "Show help"
complete -c mycommand -s v -l verbose -d "Verbose output"
# File-based completion
complete -c myapp -a "(__fish_complete_suffix .conf)" -d "Configuration files"
# Conditional completion
complete -c git -n "__fish_git_needs_command" -a "add commit push pull"
complete -c git -n "__fish_git_using_command add" -a "(__fish_git_modified_files)"
Resaltado de Sintaxis¶
# Syntax highlighting is automatic and includes:
# - Valid/invalid commands (green/red)
# - Strings and quotes
# - Variables and expansions
# - Comments
# Customize syntax highlighting colors
set -g fish_color_command blue
set -g fish_color_param cyan
set -g fish_color_redirection yellow
set -g fish_color_comment brblack
set -g fish_color_error red
set -g fish_color_escape bryellow
set -g fish_color_operator green
set -g fish_color_quote yellow
set -g fish_color_valid_path --underline
Historial y Búsqueda¶
# History search (automatic)
# Type partial command and use Up/Down arrows
# History search with specific text
# Type text and press Ctrl+R for reverse search
# History commands
history # Show all history
history search "git" # Search history for "git"
history delete --prefix "rm" # Delete commands starting with "rm"
history clear # Clear all history
# Configure history
set -g fish_history_max 10000 # Maximum history entries
Configuración y Personalización¶
Variables de Entorno¶
# Set environment variables
set -gx EDITOR vim
set -gx BROWSER firefox
set -gx PAGER less
# PATH manipulation
set -gx PATH $HOME/bin $PATH
set -gx PATH $HOME/.local/bin $PATH
set -gx PATH /usr/local/bin $PATH
# Remove from PATH
set -l index (contains -i /unwanted/path $PATH)
if test $index -gt 0
set -e PATH[$index]
end
# Conditional environment variables
if test -d "$HOME/.cargo/bin"
set -gx PATH $HOME/.cargo/bin $PATH
end
# Platform-specific variables
switch (uname)
case Darwin
set -gx HOMEBREW_PREFIX /opt/homebrew
case Linux
set -gx XDG_CONFIG_HOME $HOME/.config
end
Alias y Abreviaturas¶
# Aliases (expanded when defined)
alias ll 'ls -alF'
alias la 'ls -A'
alias l 'ls -CF'
alias grep 'grep --color=auto'
# Abbreviations (expanded when typed)
abbr -a g git
abbr -a gc 'git commit'
abbr -a gp 'git push'
abbr -a gl 'git log --oneline'
abbr -a gst 'git status'
# Conditional abbreviations
if command -v docker >/dev/null
abbr -a d docker
abbr -a dc 'docker-compose'
abbr -a dps 'docker ps'
end
# List and manage abbreviations
abbr -l # List all abbreviations
abbr -e gc # Erase abbreviation
Personalización del Prompt¶
Would you like me to continue with the remaining sections?```fish
Simple prompt function¶
function fish_prompt set_color green echo -n (whoami) set_color normal echo -n "@" set_color blue echo -n (hostname) set_color normal echo -n ":" set_color yellow echo -n (prompt_pwd) set_color normal echo -n "$ " end
Advanced prompt with Git integration¶
function fish_prompt set -l last_status $status
# User and host
set_color green
echo -n (whoami)
set_color normal
echo -n "@"
set_color blue
echo -n (hostname)
set_color normal
# Current directory
echo -n ":"
set_color yellow
echo -n (prompt_pwd)
set_color normal
# Git information
if git rev-parse --git-dir >/dev/null 2>&1
set -l branch (git branch --show-current 2>/dev/null)
if test -n "$branch"
echo -n " ("
set_color cyan
echo -n "$branch"
set_color normal
# Check for changes
if not git diff --quiet 2>/dev/null
set_color red
echo -n "*"
set_color normal
end
echo -n ")"
end
end
# Prompt symbol based on last command status
if test $last_status -eq 0
set_color green
echo -n " ❯ "
else
set_color red
echo -n " ❯ "
end
set_color normal
end
Right prompt¶
function fish_right_prompt
set_color brblack
echo -n (date "+%H:%M:%S")
set_color normal
end
### Configuración de Tema y Colorfish
Use fish_config for GUI configuration¶
fish_config
Or set colors manually¶
set -g fish_color_normal normal set -g fish_color_command blue set -g fish_color_quote yellow set -g fish_color_redirection cyan set -g fish_color_end green set -g fish_color_error red set -g fish_color_param cyan set -g fish_color_comment brblack set -g fish_color_match --background=brblue set -g fish_color_selection white --bold --background=brblack set -g fish_color_search_match bryellow --background=brblack set -g fish_color_history_current --bold set -g fish_color_operator green set -g fish_color_escape bryellow set -g fish_color_cwd green set -g fish_color_cwd_root red set -g fish_color_valid_path --underline set -g fish_color_autosuggestion 555 set -g fish_color_user brgreen set -g fish_color_host normal set -g fish_color_cancel -r set -g fish_pager_color_completion normal set -g fish_pager_color_description B3A06D yellow set -g fish_pager_color_prefix white --bold --underline set -g fish_pager_color_progress brwhite --background=cyan ```## Gestión de Paquetes y Plugins
Administrador de Plugins Fisher¶
```fish
Install Fisher¶
curl -sL https://git.io/fisher|source && fisher install jorgebucaran/fisher
Install plugins¶
fisher install jorgebucaran/nvm.fish fisher install PatrickF1/fzf.fish fisher install franciscolourenco/done fisher install jethrokuan/z
List installed plugins¶
fisher list
Update plugins¶
fisher update
Remove plugin¶
fisher remove jorgebucaran/nvm.fish
### Plugins de Fish Popularesfish
z - Directory jumping¶
fisher install jethrokuan/z
Usage: z partial_directory_name¶
fzf integration¶
fisher install PatrickF1/fzf.fish
Provides Ctrl+R for history search, Ctrl+Alt+F for file search¶
done - Desktop notifications¶
fisher install franciscolourenco/done
Notifies when long-running commands complete¶
nvm for Node.js¶
fisher install jorgebucaran/nvm.fish nvm install node nvm use node
autopair - Automatic bracket pairing¶
fisher install jorgebucaran/autopair.fish
bass - Run Bash utilities in Fish¶
fisher install edc/bass
bass source ~/.bashrc
### Instalación Manual de Pluginsfish
Create functions directory¶
mkdir -p ~/.config/fish/functions
Download and install plugin manually¶
curl -Lo ~/.config/fish/functions/fisher.fish --create-dirs https://git.io/fisher
Install from local directory¶
git clone https://github.com/user/plugin.git cp plugin/*.fish ~/.config/fish/functions/ ```## Características Avanzadas y Consejos
Operaciones Matemáticas¶
```fish
Math command for calculations¶
math 5 + 3 # 8 math 10 * 2 # 20 (escape * in some contexts) math "10 * 2" # 20 math 20 / 4 # 5 math 17 % 5 # 2
Math with variables¶
set num1 10 set num2 5 math $num1 + $num2 # 15
Advanced math functions¶
math "sqrt(16)" # 4 math "sin(3.14159/2)" # 1 math "log(10)" # 2.30259 math "pow(2, 8)" # 256
Floating point precision¶
math -s2 10 / 3 # 3.33 (2 decimal places)
### Operaciones de Archivos y Globbingfish
Basic globbing¶
ls .txt # All .txt files ls **/.py # All .py files recursively ls file?.txt # file1.txt, file2.txt, etc.
Advanced globbing patterns¶
ls *.(txt|md|rst) # Files with specific extensions ls file[1-9].txt # file1.txt through file9.txt
File test operations¶
if test -f "file.txt" echo "File exists" end
if test -d "directory" echo "Directory exists" end
if test -x "script.sh" echo "File is executable" end
File manipulation¶
cp source.txt destination.txt
mv old_name.txt new_name.txt
rm unwanted_file.txt
mkdir new_directory
rmdir empty_directory
### Gestión de Procesosfish
Background jobs¶
command & # Run in background jobs # List active jobs fg %1 # Bring job 1 to foreground bg %1 # Send job 1 to background kill %1 # Kill job 1
Process information¶
ps aux # List all processes pgrep firefox # Find process by name pkill firefox # Kill process by name
Disown processes¶
command &
disown # Detach from shell
### Redirección de Entrada/Salidafish
Output redirection¶
command > file.txt # Redirect stdout to file command >> file.txt # Append stdout to file command 2> error.log # Redirect stderr to file command &> output.log # Redirect both stdout and stderr
Input redirection¶
command < input.txt # Read input from file
Pipes¶
ls -l|grep "txt" # Pipe output to grep ps aux|grep "firefox"|wc -l # Count firefox processes
Tee command¶
command|tee file.txt # Write to file and stdout ```## Mejores Prácticas de Scripting
Estructura de Script¶
```fish
!/usr/bin/env fish¶
Script description¶
Author: Your Name¶
Date: YYYY-MM-DD¶
Function definitions¶
function usage echo "Usage: $argv[0]
function main # Parse arguments argparse 'h/help' 'v/verbose' -- $argv or return
if set -q _flag_help
usage
return 0
end
if set -q _flag_verbose
set -g verbose true
end
# Main script logic here
echo "Script execution completed"
end
Call main function with all arguments¶
main $argv
### Manejo de Erroresfish
Check command success¶
if command_that_might_fail echo "Command succeeded" else echo "Command failed with status $status" exit 1 end
Validate arguments¶
function validate_file set -l file \(argv[1] if not test -f "\)file" echo "Error: File '$file' does not exist" >&2 return 1 end return 0 end
Use in script¶
if not validate_file "important.txt"
exit 1
end
### Consideraciones de Rendimientofish
Use built-in string operations instead of external commands¶
set result (string replace "old" "new" $text) # Instead of sed set length (string length $text) # Instead of wc
Avoid unnecessary command substitutions¶
if test -f "file.txt" # Instead of if test (ls file.txt) echo "File exists" end
Use arrays efficiently¶
set files *.txt for file in $files # Instead of for file in (ls *.txt) process_file $file end ```## Depuración y Resolución de Problemas
Modo de Depuración¶
```fish
Run script with debug output¶
fish -d 3 script.fish
Enable debug in script¶
set fish_trace 1
Your commands here¶
set fish_trace 0
Function debugging¶
function debug_function
echo "Function called with arguments: $argv" >&2
echo "Current directory: "(pwd) >&2
echo "Status: $status" >&2
end
### Problemas Comunes y Solucionesfish
Issue: Command not found¶
Solution: Check PATH and command existence¶
if not command -v mycommand >/dev/null echo "mycommand is not installed or not in PATH" exit 1 end
Issue: Variable not expanding¶
Solution: Use proper Fish syntax¶
set var "value" echo \(var # Correct echo "\)var" # Also correct echo '$var' # Wrong - literal string
Issue: Function not found¶
Solution: Check function definition and loading¶
functions myfunction # Check if function exists
funcsave myfunction # Save function permanently
### Perfilado de Rendimientofish
Time command execution¶
time command
Profile function execution¶
function profile_function set -l start_time (date +%s%N) your_function \(argv set -l end_time (date +%s%N) set -l duration (math "(\)end_time - $start_time) / 1000000") echo "Function took $duration ms" end ```Fish Shell representa un cambio de paradigma en el diseño de shells, priorizando la experiencia de usuario y la capacidad de descubrimiento por encima del cumplimiento estricto de POSIX. Sus sugerencias inteligentes, resaltado de sintaxis y configuración basada en web lo hacen particularmente atractivo para principiantes en la línea de comandos, mientras que sus potentes capacidades de scripting y extenso ecosistema de plugins satisfacen las necesidades de usuarios avanzados. Aunque su sintaxis diferente requiere cierta adaptación para usuarios provenientes de shells tradicionales, el enfoque de Fish en ser útil e intuitivo lo convierte en una excelente opción para uso interactivo de shell y flujos de trabajo de desarrollo modernos.