- Quand les utilisateurs d’Unix placent des scripts personnels dans
~/bin/et les ajoutent auPATH, des noms de commandes courts peuvent entrer en conflit avec de nouvelles commandes système - Dans des environnements comme Debian/Ubuntu, qui fournissent beaucoup de commandes, le risque augmente ; sur l’ordinateur portable Ubuntu cité en exemple,
/usr/bincompte 21 733 commandes - Préfixer ses commandes personnelles par une virgule (
,) permet au shell et aux outils de la traiter comme un caractère ordinaire de nom de fichier, tout en les distinguant facilement des commandes système - La virgule se saisit sans Shift et présente moins de risques de conflit que les parenthèses, l’antislash, les deux-points, l’accent grave, l’apostrophe, la barre oblique ou le point, qui ont une signification forte dans le shell
- En appuyant sur Tab après
,, on peut parcourir directement la liste de ses commandes personnelles, ce qui facilite le maintien de noms propres pour les commandes de~/bin/
Pourquoi les noms de commandes personnelles entrent en conflit
- Beaucoup d’utilisateurs d’Unix créent un
~/bin/dans leur répertoire personnel et l’ajoutent auPATHpour utiliser des commandes pratiques et des scripts shell personnels - Le problème est que les noms de scripts personnels sont généralement de courtes combinaisons de minuscules, qui ressemblent facilement aux commandes système par défaut
- Lorsqu’une distribution Linux ajoute une nouvelle commande, son nom peut par hasard devenir identique à celui d’une commande personnelle existante
- Dans les environnements de la famille Debian, le grand nombre de commandes fournies rend ce problème plus concret
- Sur l’ordinateur portable Ubuntu cité en exemple, le décompte des commandes directement sous
/usr/bindonne21 733 apt-file search -x '^/usr/bin/[^/]*$' | wc -l
- Sur l’ordinateur portable Ubuntu cité en exemple, le décompte des commandes directement sous
Les avantages du préfixe virgule
- La solution consiste à renommer les commandes personnelles sous une forme facile à saisir, mais peu susceptible d’être choisie comme nom de commande système
- Le critère de facilité de saisie est de ne pas utiliser la touche Shift ; il n’existe pas beaucoup de caractères sûrs qui satisfont cette condition
- Les minuscules sont déjà fréquemment utilisées par les commandes système
- Les parenthèses, l’antislash, les deux-points, l’accent grave et l’apostrophe ont une signification spéciale dans le shell
- La barre oblique est le séparateur de répertoires et ne peut donc pas figurer dans un nom de fichier
- Le point désigne un fichier caché en début de nom, et sert aussi souvent de séparateur d’extension à d’autres positions
- L’option restante est la simple virgule (
,) : les outils environnants et le shell la traitent comme un caractère ordinaire dans un nom de fichier - En ajoutant une virgule comme préfixe à chaque commande personnelle, on les distingue clairement des commandes système et l’on évite plus facilement les collisions de noms
- Utilisée avec la complétion par Tab, elle permet de voir directement la liste des commandes personnelles après avoir saisi
,- La liste d’exemples comprend notamment
,complete-scp,,complete-ssh,,coreoff,,coreon,,find,,go-thpgp,,gr,,hss,,mount-thpgp,,mount-twt,,range,,svn-store-password,,umount
- La liste d’exemples comprend notamment
- Cette méthode est utilisée depuis environ 10 ans et est recommandée comme façon de garder propres les noms de commandes personnelles dans
~/bin/
2 commentaires
Commentaires sur Hacker News
Au vu du seul titre, je pensais que ce serait une idée affreuse, mais en réalité ça me plaît plutôt bien. J’aime particulièrement la partie où l’on liste tous ses outils avec Tab
Ces derniers temps, je ne rencontre pas souvent de conflits d’espace de noms, et c’est vrai qu’en étant passé au management, j’ai un peu perdu la main techniquement. J’ai l’impression que ma stack technique a dix ans de retard, et je me demande par où commencer pour me remettre à la page
Ma méthode, c’est de créer moi-même des outils qui me simplifient la vie. Par exemple, si on a au travail un service web qu’on utilise souvent pour de simples consultations, je regarde s’il a une API et j’écris un CLI pour accélérer les tâches du quotidien. Une fois que c’est bien peaufiné à mon goût, je le partage avec l’équipe, mais convaincre les autres de l’essayer est difficile. Cela dit, comme je m’en sers tous les jours, je ne m’en préoccupe pas trop
Le but était d’avoir une nouvelle perspective et de pouvoir parler des tendances, et une partie de tout ça est maintenant arrivée aussi dans mon travail. Du coup, j’ai aussi acquis une compréhension plus profonde des composants anciens
Je ne comprends pas bien le problème. Il suffit de mettre mon répertoire
binau début de$PATHplutôt qu’à la fin. Pour parcourir mes commandes, je lance simplementls ~/bin$0soit dans le chemin système, ça casse, et là commencent des heures de débogage frustrantAu final, c’est juste une question de choisir son poison
fzf. Par exemple, dans fish, on peut taper la première lettre d’une commande puis appuyer sur Tab pour faire apparaîtrefzfDu coup,
,+Tab permet de filtrer rapidement les commandes personnalisées. À l’inverse,ls ~/bindemande beaucoup plus de frappe pour une opération fréquente, ou alors il faut peut-être commencer par retrouver l’autocomplétion avecls+flèche vers le haut plusieurs foisls ~/binest bien plus lent à taper que,Pour mes wrappers légers autour de
git, j’utilise des noms de commandes personnalisés courts commeaa,st,di,dp,cm,leL’une d’entre elles entre effectivement en conflit avec un utilitaire installé par défaut sur certains systèmes. Malgré ça, comme mon répertoire
binpasse avant les répertoires système dans$PATH, c’est ma commande qui gagne, et je n’ai pas grand intérêt pour l’outil en conflit. Si un autre outil utile pour moi entrait en conflit avec l’un des miens, je lui donnerais probablement un alias qui n’entre pas en conflit, plutôt que de renommer mon outil. Ces outils à deux lettres sont trop pratiquesapt-get upgradequi lance Dwarf Fortresshttps://askubuntu.com/questions/938606/dwarf-fortress-starti...
gitsont généralement des combinaisons de deux lettres commençant parg. Par exemple,gs, c’estgit statusMais il m’arrive parfois d’avoir réellement besoin de GhostScript. C’est excellent, par exemple, pour intégrer des polices dans des fichiers PDF. En général, dans ce cas, j’utilise
env gsj. Quandjavaest arrivé, c’est devenu assez amusant. Utiliser une virgule est une idée plutôt intéressanteHeureusement que je n’avais pas choisi
k, à cause de KDE :)Par exemple, je pense que
mkfsdevrait s’appeler commesys::mkfs. La frontière entre commandes système et commandes utilisateur peut se définir de plusieurs façons, et il y aura toujours des zones grises, mais si l’on peut exécuter par accident une commande dont on ignore même l’existence et qu’on n’a jamais explicitement installée, alors elle ne devrait pas être exposée directement dans l’espace de noms global.Il y a une question connexe
J’utilise surtout Windows et, comme l’auteur, j’ai créé plusieurs scripts CLI centrés sur Python que je place à l’équivalent de
~/bin/. Si on définitpython.execomme programme par défaut pour l’extension.pyet qu’on ajoute.pyà%pathext%, on peut taper simplementhellodepuis n’importe quel chemin pour exécuter~/bin/hello.py, et je m’en sers des centaines de fois par jour. J’utilise davantage Linux ces jours-ci, mais je suis encore débutant et je n’ai pas réussi à mettre en place la même chose. On dirait que Linux n’a pas de notion de « programme associé », donc on ne peut pas simplement appeler un fichier.pyet laisser le shell l’exécuter avec Python. Bien sûr, on peut faire unchmod +xsur le script, mais il faut alors y mettre un shebang, ce qui me gêne parce que ça ressemble à du hardcoding. Je me dis que si plus tard je veux exécuter mes scripts.pyavec/usr/bin/nohtypau lieu de/usr/bin/python, ça posera problème. Et je n’ai pas non plus trouvé comment omettre la partie.pyà l’appel du script. Ce n’est pas une critique de la conception de Linux, je sais qu’il a beaucoup d’avantages, mais j’aimerais vraiment pouvoir exécuterhello.pyprésent dans le$PATHen tapanthellomy_pythondans un répertoire du chemin, puis utiliser/usr/bin/env my_pythondans le shebangSi tu veux une approche plus propre, regarde l’outil
update-alternatives. Il fournit ce type d’abstraction de manière plus générale : https://linuxconfig.org/how-to-set-default-programs-using-up...Sous Linux — et en fait sur la plupart des plateformes hors Windows — la signification des extensions de fichier est bien plus faible. La possibilité d’exécuter n’importe quel type de fichier dépend non pas de son extension, mais de choses comme le drapeau
+x. Cela permet de réécrire une commande dans un autre langage d’implémentation sans casser les appels qui la visent. L’extension.pyn’a de sens que pour les modules importés ; pour un script exécutable, il suffit de regarder le shebang quand c’est nécessaire. Les scripts distribués à l’extérieur utilisent en général#!/usr/bin/env python, tandis que ceux inclus dans des paquets de distribution sont souvent réécrits en#!/usr/bin/pythonou équivalent. Le shebang ne prend pas en charge plusieurs arguments, mais GNUenvpropose l’option-Spour imiter ce comportement. Cela dit, le problème de longueur des arguments demeure.pydu nom du fichier. L’appeler"hello"est tout à fait acceptableJe vois mal quels seraient les inconvénients du shebang. Si tu veux vraiment l’exécuter avec un autre interpréteur, il suffit de le préciser, par exemple
"nohtyp hello". Et si ça te dérange vraiment, tu peux définir un alias dans ton fichier d’initialisation du shell. Avec bash, par exemple :alias hello="python3 /path/to/hello.py". Si tu en as envie, tu peux même écrire un petit script qui crée automatiquement ce genre d’alias pour le contenu d’un répertoire donnéDans les scripts shell, on ajoute généralement un shebang et on rend le fichier exécutable, de sorte que l’exécutable soit déclaré dans le script lui-même. On peut considérer le shebang comme une sorte d’extension de fichier. Si
chmod +x ./malware.pypuis./malware.pyne fonctionnent pas, il faut vérifier le chemin indiqué par le shebang. Si l’interpréteur peut exécuter le script comme un argument ordinaire, on peut aussi obtenir un comportement similaire avec quelque chose commexdg-open malware.py. Ce serait l’équivalent d’un double-clic dans le gestionnaire de fichiers par défaut. Quand j’utilisais Linux comme système principal de bureau, j’avais un aliasxop, mais je ne l’utilisais que pour les fichiers de données comme les images ou les documents, pour lesquels le comportement par défaut était déjà le bon. Je ne recommande pas de définir l’interpréteur comme programme par défaut pour les scripts exécutables. Par défaut, on peut aussi vouloir ouvrir un script dans un éditeur plutôt que l’exécuter. Je pense quexdg-openest plutôt un outil côté Gnome, mais ça ne veut pas dire qu’il est inutilisable ailleurs ; je l’ai aussi utilisé sous Xubuntu. Si tu veux vraiment que tous les fichiers Python s’exécutent par défaut aussi en contexte GUI, il doit être possible de configurer ce comportement, etman xdg-openpeut aider. Encore une fois, ce n’est pas un bon conseil#!/usr/bin/env pythonAinsi, c’est le
pythontrouvé en premier dans le chemin qui sera exécuté. Si plus tard tu veux utiliser/usr/bin/nohtypau lieu de/usr/bin/python, tu peux créer un lien symboliquepythonpointant vers/usr/bin/nohtypdans un répertoire recherché avant/usr/bin. Par exemple, il suffit d’ajouter~/myCommandPreferencesau début du$PATHUne autre manière d’éviter les conflits dans le
$PATHconsiste à donner au binaire un nom très long, peu susceptible d’être utilisé par d’autres exécutables, puis à définir un alias court dansbashrcLes alias n’affectent pas les exécutables appelés à l’intérieur des scripts, et dans mes scripts je peux continuer à faire référence au nom long. L’inconvénient, c’est qu’on n’obtient pas le même niveau d’ergonomie avec l’autocomplétion par tabulation, même si cet aspect est vraiment agréable. Il peut aussi rester des conflits pour des scripts qui, comme le script d’activation de
venven Python, doivent êtresourceplutôt qu’exécutés comme sous-processus, mais ce cas reste rarezsh, on a aussi cette autocomplétionLe fait de commencer par une virgule est aussi une technique courante dans la communauté des text expanders / remplacements de texte
,J’ai récemment regardé dans
~/.local/bin/et j’y ai trouvé des dizaines d’exécutables que je ne me souvenais pas avoir mis làLa plupart étaient liés à pyside, mais il y avait aussi d’autres scripts. J’ai dû les ouvrir un par un pour me rappeler lesquels j’avais écrits moi-même et lesquels venaient d’ailleurs. Si mes scripts avaient commencé par une virgule, ça aurait été beaucoup plus rapide, et ça m’aurait aussi aidé à me souvenir de la raison de leur création avant même de les ouvrir
~/.local/bin/sert aux scripts installés, tandis que ce qu’on écrit soi-même en local va dans~/bin/Je passe mon tour. Il suffit de mettre le
binpersonnel avant$PATH, et d’utiliser/usr/binou/binquand on veut référencer un programme masquéOn peut lister les outils personnalisés avec
~/bin/[Tab]Si je n’aime pas le
grepdu système, par exemple legrepde Solaris, et que je préfère legrepde GNU, pourquoi ne pas simplement le laisser sous le nomgrep?Le fait d’avoir découvert cette idée il y a cinq ans m’a permis de mettre de l’ordre dans mon recueil d’astuces shell. En combinant des alias et
~/bin, j’ai maintenant plus de 50 commandes virgule, et ma vie dans le shell est bien plus fluide qu’avant, quand tout était mélangéCela a aussi été discuté en 2020 : https://news.ycombinator.com/item?id=22778988 (90 commentaires)
, macroexpandStart all of your commands with a comma (2009) - https://news.ycombinator.com/item?id=31846902 - juin 2022 (121 commentaires)
Start all of your commands with a comma (2009) - https://news.ycombinator.com/item?id=22778988 - avril 2020 (89 commentaires)
Que pensez-vous d’utiliser « _ » ?