Zsh

De Le Wiki du Forum-Debian.fr
Aller à la navigation Aller à la recherche

zsh est un shell alternatif à bash ou au bourne shell (/bin/sh). Il possède énormément de fonctionnalités. Cette page n'est pas faite pour découvrir comment utiliser un shell mais plutôt pour présenter des fonctionnalités intéressantes de zsh.

globbing étendu

Les globbing c'est l'expansion de chemin de fichier. C'est ce qui fait que *.pdf est remplacé par fic1.pdf fic2.pdf en fonction des fichiers qui se trouvent dans le répertoire courant. Ça existe dans tous les shell, mais zsh va plus loin que la plupart des autres avec les globbings étendus.

Pour s'en servir il faut utiliser les options EXTENDEDGLOB et NULL_GLOB comme ceci :

setopt EXTENDEDGLOB NULL_GLOB

ça c'est à placer dans ${HOME}/.zshrc avec cela on peut utiliser le très connu :

cmd **/*

qui va passer à la commande cmd tout les fichiers du répertoire courant et des répertoires en dessous. Il est possible de l'obtenir aussi en bash 4 ou superieur (le bash de squeeze possède cette option) grâce à l'option shopt -s globstar).

Mais on peut faire des choses bien plus fines :

du -sh *(.D)

Si je veux pas les fichier cachés :

du -sh *(.)

Si je ne veux que les répertoires cachés ou non :

du -sh *(/D)

Si je ne veux pas les répertoires cachés :

du -sh *(/)

Autrement dis :

  • / pour chercher les répertoires
  • . pour les fichiers (sans les répertoires)
  • D pour prendre en compte les noms qui commencent par . (et qui sont donc cachés)
  • N permet de ne pas avoir d'erreur si aucune correspondance n'est trouvée

Il y en a pleins d'autres. Vous voulais en savoir plus ?

man zshexpn

Quand il y en a marre des globbings

Des fois les globbins c'est assez lourd car il faut protéger tout un tas de caractères. Dans ces cas là, zsh possède un builtin noglob qui s'utilise ainsi

noglob find /répertoire -name *.jpg


grâce à noglob, il n'est plus la peine de protéger les * (évidement ça peut s'ajouter dans un alias).

renommage massif

Encore un truc intéressant. Quand on commence à faire du shell et qu'on lis pas les man on a tendance à faire ça :

var=$(echo $var | sed -e 's/-/_/g)

Pour remplacer le - par des _ dans le contenu d'une variable (oui je sais tr permet aussi de le faire).

zsh possède une syntaxe pour ne pas avoir à utiliser sed :

v='c-o-u-c-o-u'
echo ${v/-/_} # affiche c_o-u-c-o-u
echo ${v:s/-/_} # affiche c_o-u-c-o-u
echo ${v:gs/-/_} # affiche c_o_u_c_o_u


Bon ça c'est bien sympa, mais si j'en parle c'est uniquement pour montrer autre chose qui déchire. Souvent dans la vie quotidienne sur son shell on a à faire du renommage en masse est c'est pas génial à faire, sauf sous zsh ! Première chose :

autoload -U zmv

cela permet d'avoir la commande zmv le mv amélioré de zsh. Je pense que l'autodocumentation montre des exemples très parlant :

$ zsh
Usage:
  zmv [OPTIONS] oldpattern newpattern
where oldpattern contains parenthesis surrounding patterns which will
be replaced in turn by $1, $2, ... in newpattern.  For example,
  zmv '(*).lis' '$1.txt'
renames 'foo.lis' to 'foo.txt', 'my.old.stuff.lis' to 'my.old.stuff.txt',
and so on.  Something simpler (for basic commands) is the -W option:
  zmv -W '*.lis' '*.txt'
This does the same thing as the first command, but with automatic conversion
of the wildcards into the appropriate syntax.  If you combine this with
noglob, you don't even need to quote the arguments.  For example,
  alias mmv='noglob zmv -W'
  mmv *.c.orig orig/*.c

Donc on décris une expression régulière pour décrire la forme des fichiers à renommer puis on indique comment les renommer. On peut même faire des choses comme ça :

c=1 zmv '(*).JPEG' 'photo$((c++)).jpg'

Ce qui est gênant quand on fait ça c'est qu'il va y avoir un fichier photo1.jpg et un fichier photo10.jpg et que l'ordre va être photo10.jpg photo11.jpg … photo1.jpg photo20.jpg … photo2.jpg etc. Pour pallier ça il faut combler avec des 0. Pour ça on va utiliser cette commande :

c=1 zmv '(*).JPEG' 'photo${(l:4::0:)$((c++))}.jpg'

Ça indique qu'on souhaite combler avec les 0 pour que le nombre soit toujours sur 4 digits.

Dernière astuce retirer les espace de tout les noms de fichiers du répertoire courant :

zmv '(*)' '${1:gs/ //}'

zmv supporte certaines options très classique de mv (-i -f -v), il possède une option très pratique -n qui permet de ne pas exécuter la commande mais de vérifier si les arguments font bien ce que l'on veux.

Il existe aussi zcp et zln.

C'est un bon exemple de la forte cohérence de la syntaxe de zsh. Il n'y a pas de cas particulier ce que l'on peut faire sur une variable on peut le faire sur n'importe quel variable dans n'importe quel contexte.

alias

Les alias de suffixe se définissent avec l'option -s d'alias. Il se crée ainsi :

alias -s ext='cmd'

Il permet ensuite d'écrire des commandes de la forme (cmd peut évidement avoir des arguments) :

./path/to/file.ext

Qui exécuteras alors :

cmd ./path/to/file.ext

Par exemple avec l'alias :

alias -s pdf='xpdf'

un peut lire les fichiers pdf avec la commande :

./chemin/fichier.pdf

Les alias globaux permettent d'écrire des alias pour les utiliser ailleurs qu'en début de commande. L'exemple le plus classique c'est ça :

alias -g C='| wc -l'

ensuite une commande comme

lspci C

donneras la liste des périphériques PCI de l'ordinateur.

Mais il y a plus efficace que ça, les abréviations ! Ca c'est vraiment un truc dont je ne peux plus me passer. Dans mon .zshrc j'ai ça :

typeset -Ag abbreviations
abbreviations=(
  "Ia"    "| awk"
  "Ig"    "| grep"
  "Ip"    "| $PAGER"
  "Ih"    "| head"
  "It"    "| tail"
  "Is"    "| sort"
  "Iw"    "| wc"
)

Après avoir écris une commande il me suffit de taper "Ig " (donc un i majuscule (I) suivi d'un g et d'un espace pour voir ajouter "| grep" (à la place de Ig). C'est très agréable à utiliser.

Liens