zsh the powerful shell

wizard of zsh La shell è l’interfaccia per eccellenza degli smanettoni.

Quando si comincia a farne un utilizzo costante, si sente il bisogno di spingersi oltre, scoprendo/creando delle funzionalità che ci semplificano ulteriormente la vita.

Almeno questa è stata la mia reazione… un bel po’ di tempo fa.

Dopo aver provato a personalizzare la bash, mi resi conto che le mancavano molte funzionalità presenti in altre shell. Decisi di cambiare proprio tipo di shell ed iniziai ad utilizzare la tcsh, una versione migliorata di csh.

Ero abbastanza soddisfatto della mia configurazione, quando un amico mi parlò di zsh.

funzionalità

Questa potente shell, come moltissimi progetti informatici (vedi ruby), prende il meglio delle caratteristiche da altri progetti simili e aggiunge, tramite un ottimo collante, altre funzionalità originali.

Si può considerare questa shell come una sorta di superset di sh, ash, bash, csh, ksh, e tcsh.

Qualche anno fa avevo pure fatto un piccolo screencast che illustrava alcune caratteristiche di zsh…

Andiamo a vedere nel dettaglio alcune delle funzionalità più importanti.

Command line completition

In zsh il completamento non si limita ai nomi dei programmi, ma include anche i vari argomenti ed i parametri degli stessi.

Costruendoli anche dinamicamente.

Il tutto completamente personalizzabile.

Tra le altre cose, questa funzionalità integra un sistema di caching, per i completamenti più dispendiosi (es: il completamento di tutti i nomi dei programmi disponibili nei repository debian)

Un’altra interessante caratteristica del sistema di completamento è il correttore ortografico.

File globbing

Il potentissimo file globbing di zsh permette di specificare una determinata categoria di file, facendo a meno di utilizzare programmi esterni come find/args.

Vediamolo in azione:

# tutti i file nella directory /tmp e nelle relative sottodirectory, di proprietà dell'utente kalos
ls -l /tmp/**/*(u:kalos:)

# tutti i file regolari (non symlink, dir, ecc)
ls -l /boot/*(.)

# tutti i file regolari ed eseguibili
ls -l /bin/*(.x)

# tutti i file che non hanno abilitata la scrittura per il gruppo di appartenenza
ls -l /tmp/**/*(.:g-w:)

# tutti i file piu' vecchi di 20 minuti
ls -l /tmp/.(mm+20)

# tutti i file vuoti
ls -l /tmp/*(.L0)

# tutti i file (comprese le directory) senza estenzione
ls -ld ^?/./(D)

Gestione avanzata di variabili e array

  • Sostituzione delle variabili
FILE="/home/kalos/doc/ruby/rspec.pdf"

# stampa il contenuto della variabile $FILE sostituendo le occorrenze di "kalos" con "marco"
echo ${FILE//kalos/marco} » /home/marco/doc/ruby/rspec.pdf

# stampa solo il nome del file (come il programma "basename")
echo ${FILE##*/} » rspec.pdf

# stampa solo il percorso del file (come "dirname")
echo ${FILE%//./} » /home/kalos/doc/ruby

# elimina l'estensione nella stringa salvata nella variabile
FILE="rspec.pdf" echo $FILE:r » rspec

# per ulteriori informazioni
man 1 zshexpn
  • Array ed array associativi

Questa funzionalità è molto utile se si stanno creando degli script non proprio banali.

array=(foo bar lillo boom)

# stampa l'ultimo elemento
echo $array[-1]
» boom

# stampa dal secondo al penultimo elemento
echo $array[2,-2]
» bar lillo

# dichiarazione di un array associativo
typeset -A array_ass

# inizializzazione dell'array
array_ass=(uno 1 due 2 tre 3 quattro 4)

# stampa solo le chiavi
print ${(k)array_ass}
» uno due tre quattro

# stampa i valori
print ${(v)array_ass}
» 1 2 3 4

# ordina le chiavi in base ai nomi
print ${(ok)array_ass}
» due quattro tre uno

# modifica il valore di un array associativo
array_ass[tre]='03'

# stampa l'array ordinato
print ${(o)array_ass}
» 03 1 2 4

Alias

Zsh amplia il concetto di aliasing introducendo:

  • alias globale

È un tipo di alias che può essere utilizzare in qualsiasi parte della riga di comando e non solo all’inizio.

# definizione degli alias
alias -g Il="| less"
alias -g N="&>/dev/null"

# manda in pipe il file letto con cat a less
cat /var/log/messages Il

# redirige lo standard output e lo standard error nel nulla
rm -rf /tmp N
  • alias dei suffissi

Se si esegue un file con un certo suffisso, viene automaticamente eseguito il programma associato

alias -s txt=$EDITOR
alias -s {mpg,mpeg,avi,ogm,wmv,m4v,mp4,mov,mkv}="mplayer"

# come un nerd guarda un film ;)
~FILM/totoro.avi

Modalità compatibilità

Zsh ha la possibilità di emulare il comportamento delle shell csh, sh e ksh (la sua parente più vicina).

Questo ci permette, ad esempio, di utilizzare la nostra shell come shell predefinita di sistema per tutti gli script di init, ecc.

Le modalità di compatibilità possono essere eseguite in due modi:

  • creando un link della shell da emulare che punta al binario di zsh (ln -s /bin/zsh /bin/csh). In questo caso si ottiene un’emulazione completa della shell.

  • abilitando selettivamente tutte le funzionalità da emulare, ad esempio con “setopt KSH_GLOB”

History condiviso da più sessioni contemporaneamente

Questa funzionalità può tornare utile, ad esempio, quando più persone stanno lavorando sullo stesso sistema e vogliono condividere i comandi lanciati

configurazione

La configurazione di zsh non è tra le più semplici.

Per facilitare le cose, è stato realizzato un bel progetto collaborativo.

oh-my-zsh

E’ un piccolo framework che fornisce una configurazione abbastanza completa ed un sistema di plugin aggiuntivi.

installazione

wget --no-check-certificate https://github.com/robbyrussell/oh-my-zsh/raw/master/tools/install.sh -O - | sh

utilizzo

Per utilizzarlo basta modificare il file ~/.zshrc per abilitare qualche plugin e configurare il tema del prompt preferito.

aggiornamento

Una delle funzionalità più importanti di questo framework è il costante aggiornamento effettuato dalla vasta comunità che ci lavora.

Di default il programma chiede di auto-aggiornarsi ogni settimana, attraverso il file oh-my-zsh/tools/upgrade.sh, che non fa altro che eseguire il comando “git pull origin master”.

come gestire un proprio fork di OMZ

Se si vuole gestire la propria configurazione di zsh attraverso OMZ, questi sono i semplici passi da compiere:

  • fare il fork del progetto su github
  • aggiungere al repository git l’url del repository ufficiale di OMZ
git remote add upstream git://github.com/robbyrussell/oh-my-zsh.git
  • modificare il file tools/install.sh sostituendo git pull origin master con git fetch upstream && git merge upstream/master

risorse utili

Altri rifetimenti in merito li potete trovare nei miei bookmark salvati su delicious