Vai al contenuto

Fish - Shell Interattivo Amichevole

Fish (Friendly Interactive Shell) è un shell a riga di comando intelligente e user-friendly progettato per l'uso interattivo, l'usabilità e la scopribilità. Creato da Axel Liljencrantz nel 2005, Fish adotta un approccio diverso rispetto agli shell tradizionali, dando priorità all'esperienza utente e fornendo impostazioni predefinite sensibili fin da subito. A differenza degli shell conformi a POSIX, Fish offre evidenziazione della sintassi, suggerimenti automatici, completamenti con tab che funzionano senza configurazione, e una sintassi pulita e moderna che mira a essere più intuitiva e meno soggetta a errori rispetto ai linguaggi shell tradizionali.

Installazione e Configurazione

Installazione di 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

Impostare Fish come Shell Predefinito

# 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

Configurazione Iniziale

# 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

Struttura Base della Configurazione

# 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

Sintassi e Caratteristiche del Linguaggio Fish

Variabili e Scope

# 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

Sostituzione di Comandi

# 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

Manipolazione delle Stringhe

# 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

Istruzioni Condizionali

# 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

Cicli e Iterazione

# 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

Funzioni e Scripting

Definizione di Funzioni

# 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

Funzionalità Avanzate delle Funzioni

# 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

Gestione degli Errori

# 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

Funzionalità Interattive

Suggerimenti Automatici

# 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

Completamenti con Tab

# 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)"

Evidenziazione della Sintassi

# 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

Cronologia e Ricerca

# 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

Configurazione e Personalizzazione

Variabili di Ambiente

# 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 e Abbreviazioni

# 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

Personalizzazione 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 ### Configurazione del Tema e dei Colorifish

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 ```## Gestione dei Pacchetti e Plugin

Gestore di Plugin 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 ### Plugin Fish Popolarifish

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 ### Installazione Manuale di Pluginfish

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/ ```## Funzionalità Avanzate e Suggerimenti

Operazioni Matematiche

```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) ### Operazioni sui File e 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 ### Gestione dei Processifish

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 ### Reindirizzamento Input/Outputfish

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 ```## Migliori Pratiche di Scripting

Struttura dello 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 ### Gestione degli Errorifish

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 ### Considerazioni sulle Prestazionifish

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 ```## Debug e Risoluzione dei Problemi

Modalità Debug

```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 ### Problemi Comuni e Soluzionifish

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 ### Profilazione delle Prestazionifish

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 rappresenta un cambiamento di paradigma nel design delle shell, dando priorità all'esperienza utente e alla scoperta rispetto alla stretta conformità POSIX. I suoi suggerimenti intelligenti, l'evidenziazione della sintassi e la configurazione basata sul web lo rendono particolarmente attraente per i nuovi utenti della riga di comando, mentre le sue potenti capacità di scripting e l'ampio ecosistema di plugin soddisfano le esigenze degli utenti avanzati. Sebbene la sua sintassi diversa richieda un certo adattamento per gli utenti provenienti da shell tradizionali, l'attenzione di Fish verso l'essere utile e intuitivo lo rende un'eccellente scelta per l'uso interattivo della shell e per i flussi di lavoro di sviluppo moderni.