8 fonctions shell essentielles pour améliorer votre ligne de commande Linux
Une fois que vous avez acquis une solide compréhension de Linux et maîtrisé les différentes commandes disponibles, votre prochain grand gain se présente sous la forme de fonctions shell. Le code enveloppé dans une fonction peut être réutilisé par vos scripts shell, mais vous pouvez également le rendre disponible sur votre ligne de commande, tout comme vous utiliseriez n'importe quel programme, commande intégrée ou alias.
Des fonctions courtes qui effectuent des tâches courantes peuvent vous faire gagner beaucoup de temps et sont satisfaisantes à assembler. Voici quelques-unes des fonctions shell que j’ai trouvées les plus utiles.
Sommaire
1
mkd : créez un répertoire et entrez-le
Je commence par un exemple de fonction shell idéale : c'est utile et facile à comprendre, mais cela devrait aider à illustrer certains concepts clés. À la base, une fonction shell encapsule une ou deux commandes que vous souhaiterez peut-être souvent exécuter ensemble, ce qui est plus pratique.
À quand remonte la dernière fois que vous avez exécuté la commande mkdir pour créer un répertoire et que vous n'avez pas immédiatement exécuté cd pour accéder à ce répertoire ? Je suppose que ce n'est probablement jamais le cas, alors pourquoi ne pas compléter mkdir avec une version qui fait exactement cela ? Voici la fonction :
mkd() {
mkdir -p -- "$1" && cd -P -- "$1"
}
Vous pouvez conserver toutes vos fonctions shell personnalisées dans un fichier et les sourcer au démarrage. Je garde les miens dans un répertoire caché chez moi, j'exécute donc cette commande depuis mon fichier ~/.zshrc pour les charger dans mon shell : . ~/.config/shell_funcs.sh.
Le && ici est une astuce de terminal astucieuse qui exécute la deuxième commande après la première, mais seulement si la première réussit. Dans ce cas, cela ne sert à rien de passer au répertoire s'il n'a pas été créé, à cause d'un problème de permission par exemple.
L'option mkdir -p vous permet de créer plusieurs niveaux de répertoire : mkd docs/lettres/urgentPar exemple. Cela a un effet secondaire intéressant : si vous exécutez cette fonction et lui transmettez un répertoire qui existe déjà, vous ne verrez aucune erreur, mais vous finirez quand même par changer de répertoire.
La dernière chose à noter concerne les arguments « – ». Il s'agit d'un argument spécial qui indique la fin des options et le début d'autres arguments : les noms de répertoires, dans ce cas. Ceci est un exemple de programmation défensive pour éviter les problèmes si vous essayez de créer un répertoire commençant par un caractère « – ». Cela peut sembler improbable, mais il vaut toujours mieux prévenir que guérir.
2
invite : définissez votre invite sur diverses choses
L'une des premières choses que tout le monde apprend sur son shell Linux est de savoir comment personnaliser l'invite. Au début de chaque ligne de commande, votre shell imprimera du texte pour vous indiquer qu'il est prêt à être saisi :
L'invite ci-dessus affiche le répertoire actuel entre parenthèses, suivi d'un signe dollar, mais l'invite peut être aussi minimale ou informative que vous le souhaitez. Sa valeur est contrôlée par une variable d'environnement nommée PS1. Vous pouvez définir cela sur une chaîne fixe, comme « $ », n'oubliez pas d'échapper au $, qui a une signification particulière pour le shell :
PS1="$ "
La fonction suivante définit l'invite sur quelque chose d'un peu plus dynamique. Cette version vérifie si vous exécutez bash ou zsh, elle peut donc être utilisée par l'un ou l'autre shell. Ils diffèrent légèrement dans leurs capacités : chacun essaie d'afficher uniquement les trois dernières parties de votre chemin actuel, mais bash ajoute sa propre logique par-dessus.
prompt() {
NEWLINE=$'n' if ( ! "${BASH_VERSINFO}" == "" ); then
PROMPT_DIRTRIM=3
PS1="${NEWLINE}(w) $ "
fi
if ( ! "${ZSH_VERSION}" == "" ); then
PS1="${NEWLINE}(%3~) $ "
fi
}
Cette invite inclut également un caractère de nouvelle ligne, qui est plus facile à ajouter en définissant d'abord une variable. Cette nouvelle ligne crée une ligne vide entre la sortie de la commande précédente et l'invite suivante, ce qui facilite le regroupement des commandes et leur sortie en un coup d'œil.
Bien que bash et zsh gèrent l'invite plus ou moins de la même manière, les autres shells ne sont pas aussi cohérents. Certains coquillages plus modernes, comme le poisson, adoptent une approche fonctionnelle de l'invite, offrant beaucoup plus de flexibilité. Si vous n'utilisez pas bash ou zsh, consultez le manuel de votre shell pour savoir comment configurer l'invite.
Mais pourquoi avoir une fonction pour faire cela, au lieu de simplement la définir une fois dans votre fichier ~/.bashrc ou ~/.zshrc ? Eh bien, je trouve très utile d'avoir différentes invites vers lesquelles je peux facilement basculer :
C'est très pratique pour prendre des captures d'écran de mon terminal lorsque je souhaite masquer mon chemin actuel. Mais vous pouvez l'utiliser dans d'autres situations : pour faire la différence entre deux sessions de terminal, par exemple, ou pour économiser de l'espace sur l'écran dans des fenêtres plus petites.
3
trim : supprime les espaces de début et de fin
Cette fonction supprime les espaces au début et à la fin de chaque ligne :
trim() {
sed 's/^( t)*//;s/( t)*$//'
}
La ligne de commande Linux consiste à transmettre des données d'une commande à une autre, via des canaux, des fichiers, etc. Mais cela nécessite des données propres et prévisibles, et les commandes ne sont pas toujours efficaces pour les produire. Prenons par exemple les toilettes :
Cette sortie utilise l'alignement pour produire une liste agréable et lisible, mais elle est difficile à utiliser dans un pipeline car d'autres commandes devront tenir compte de cet espace de début. Au lieu de cela, diriger la sortie vers le découpage supprimera les espaces supplémentaires, ce qui rendra le traitement ultérieur plus simple :
Cette fonction de trim utilise sed, l'utilitaire d'édition de flux. Il spécifie deux remplacements, séparés par un point-virgule. Le premier recherche une série de caractères espace/tabulation au début de chaque ligne et la remplace par rien, c'est-à-dire la supprime. Le deuxième remplaçant fait de même, mais en bout de ligne.
Notez que sed fonctionne sur une entrée standard si aucun nom de fichier ne lui est transmis, et l'appeler via une fonction comme celle-ci fait la même chose, en transmettant l'entrée standard à la commande.
4
rgrep : un raccourci pour grep récursif
Parfois, une fonction n’est pas plus simple qu’une seule commande, dotée d’options spécifiques. Bien qu'une commande rgrep puisse exister sur votre système et faire à peu près la même chose que cette fonction, elle n'est pas présente sur macOS, j'utilise donc cette alternative :
rgrep() {
grep -Id recurse "$@"
}
L'option -I empêche grep de rechercher dans les fichiers binaires, ce qui ne produit généralement que des erreurs. L'indicateur -d spécifie comment grep doit traiter les répertoires ; dans ce cas, « recurse » entraîne leur lecture récursive.
Notez l'utilisation de « $@ » pour transmettre des arguments supplémentaires à grep. Ceci est important car cela signifie que vous pouvez exécuter « rgrep » exactement comme vous exécuteriez « grep », il aura simplement votre comportement personnalisé. Par exemple, rgrep -je fais tout s'étendra à grep -Id recurse -i todo.
Vous pouvez confirmer comment cela fonctionne en ajoutant « set -o xtrace » au début de votre fonction pour imprimer les commandes lors de leur exécution. C'est l'un des meilleurs moyens de peaufiner vos scripts shell, car cela vous aide à déboguer exactement ce qui se passe sous le capot.
5
ucase/lcase : conversion entre les cas
La plupart des langages de programmation ont une fonction majuscule/minuscule ; même des applications comme LibreOffice intègrent cette fonctionnalité car elle est souvent très utile. Vous pouvez facilement avoir l'équivalent sur votre ligne de commande Linux, où il est encore plus puissant, puisqu'il peut opérer sur chaque ligne d'un fichier que vous envoyez :
ucase() {
tr '(:lower:)' '(:upper:)'
}lcase() {
tr '(:upper:)' '(:lower:)'
}
Cette paire de fonctions complémentaires utilise la commande tr, qui effectue des transformations simples sur un flux de texte.
tr prend deux arguments : une liste de caractères à rechercher et une liste de caractères par lesquels les remplacer. Chaque caractère de remplacement agit sur celui correspondant dans la chaîne de recherche, donc « tr 'AB' 'ab' » convertira « A » en « a » et « B » en « b ». Les classes de caractères spéciaux « (:upper:) » et « (:lower:) » s'étendent à l'ensemble complet des caractères majuscules et minuscules dans les paramètres régionaux actuels.
6
aujourd'hui : obtenez la date actuelle au format ISO court
today() {
date '+%Y-%m-%d'
}
Oubliez pour le moment la différence entre les dates américaines et celles du reste du monde : ce format de date n'est vraiment utilisé par personne, mais c'est sans conteste mon préféré. La raison est simple : les dates sous cette forme seront triées naturellement, et c'est un énorme bonus à mon avis. J'utilise le format à de nombreux endroits : noms de fichiers, titres de documents, bases de données, etc.
Il s’agit peut-être d’un autre raccourci de commande simple, mais il est très pratique. Le format exact de la date est ennuyeux à retenir : le préfixe « + », les symboles « % » et la casse correcte de chaque partie. Je préfère de loin oublier tout ça et simplement écrire aujourd'hui au contraire : très satisfaisant !
7
filesize : affiche les fichiers dans le répertoire courant, classés par taille
Une tâche de maintenance courante que je dois effectuer consiste à nettoyer de gros fichiers. Bien que ncdu soit un excellent moyen de localiser des fichiers volumineux, il est parfois excessif. Ce que je veux souvent, c'est voir quels fichiers de mon répertoire actuel sont les plus gros.
filesize() {
du -sk * | sort -n
}
du est l'outil d'utilisation du disque ; il indique la quantité d'espace occupée par chaque fichier, y compris les répertoires, dont il rend compte de manière récursive. Ainsi, cette fonction vous indiquera la taille totale de tous les répertoires présents, ce qui facilitera l'exploration de votre système de fichiers et l'élimination de tous les fichiers indésirables.
8
paths : affiche joliment la variable PATH
paths() {
echo $PATH | tr ':' 'n'
}
Une autre tâche de maintenance que j'aime effectuer de temps en temps est de nettoyer mon PATH. macOS a la mauvaise habitude d'ajouter des répertoires supplémentaires à la variable d'environnement, y compris certains qui n'existent pas réellement ! Mais comme cette variable utilise des deux-points pour séparer chaque chemin, elle peut être assez difficile à lire :
Cette fonction rend le résultat beaucoup plus agréable :
C'est une autre excellente utilisation de ce brillant programme tr, et vous pouvez l'étendre davantage : en vérifiant que chaque répertoire de votre PATH existe, par exemple :
check_paths() {
paths | while read path
do
if ( ! -d "$path" ); then
echo "bad PATH: dir does not exist: $path" >&2
fi
done
}
