Beginnen Sie alle Befehle mit einem Komma (2009)
(rhodesmill.org)- Wenn Unix-Nutzer persönliche Skripte in
~/bin/ablegen und zuPATHhinzufügen, können kurze Befehlsnamen mit neuen Systembefehlen kollidieren - In Umgebungen mit vielen bereitgestellten Befehlen wie Debian/Ubuntu ist das Risiko noch größer; auf einem Beispiel-Ubuntu-Laptop wurden 21.733 Befehle in
/usr/bingezählt - Wenn man persönlichen Befehlen ein Komma (
,) voranstellt, behandeln Shell und Werkzeuge es als normales Dateinamenzeichen, während es sich zugleich leicht von Systembefehlen unterscheiden lässt - Das Komma kann ohne Shift eingegeben werden und birgt weniger Konfliktpotenzial als Klammern, Backslash, Doppelpunkt, Backtick, einfaches Anführungszeichen, Slash oder Punkt, die in der Shell eine starke Bedeutung haben
- Drückt man nach
,die Tab-Taste, kann man die Liste persönlicher Befehle sofort durchgehen, was es erleichtert, Befehlsnamen in~/bin/sauber zu halten
Warum persönliche Befehlsnamen kollidieren
- Viele Unix-Nutzer erstellen in ihrem Home-Verzeichnis ein
~/bin/und fügen es zuPATHhinzu, um persönliche Komfortbefehle und Shell-Skripte zu verwenden - Das Problem ist, dass persönliche Skriptnamen meist aus kurzen Kombinationen aus Kleinbuchstaben bestehen und damit leicht Systembefehlen ähneln
- Wenn Linux-Distributionen neue Befehle hinzufügen, kann ein vorhandener persönlicher Befehl zufällig denselben Namen bekommen
- In Debian-basierten Umgebungen mit ihrer großen Zahl bereitgestellter Befehle wird dieses Problem besonders realistisch
- Zählt man auf einem Beispiel-Ubuntu-Laptop die Befehle direkt unter
/usr/bin, kommt man auf21.733 apt-file search -x '^/usr/bin/[^/]*$' | wc -l
- Zählt man auf einem Beispiel-Ubuntu-Laptop die Befehle direkt unter
Die Vorteile des Komma-Präfixes
- Die Lösung besteht darin, persönliche Befehlsnamen so zu verändern, dass sie leicht einzugeben sind, aber kaum als Systembefehlsnamen gewählt werden
- Das Kriterium für gute Eingabefreundlichkeit ist, die Shift-Taste nicht benutzen zu müssen; unter dieser Bedingung gibt es nicht viele sichere Zeichen
- Kleinbuchstaben werden bereits häufig in Systembefehlen verwendet
- Klammern, Backslash, Doppelpunkt, Backtick und einfaches Anführungszeichen haben in der Shell eine besondere Bedeutung
- Der Slash ist ein Verzeichnistrenner und kann nicht in Dateinamen vorkommen
- Der Punkt steht am Anfang eines Dateinamens für eine versteckte Datei und wird auch sonst oft zur Trennung von Erweiterungen verwendet
- Die verbleibende einfache Wahl ist das Komma (
,), und die umliegenden Werkzeuge sowie die Shell behandeln das Komma als normales Zeichen in Dateinamen - Wenn man jedem persönlichen Befehl ein Komma voranstellt, lässt er sich klar von Systembefehlen unterscheiden, sodass Namenskollisionen leichter vermieden werden können
- In Verbindung mit Tab-Vervollständigung kann man nach Eingabe von
,sofort die Liste persönlicher Befehle prüfen- Die Beispiel-Liste enthält
,complete-scp,,complete-ssh,,coreoff,,coreon,,find,,go-thpgp,,gr,,hss,,mount-thpgp,,mount-twt,,range,,svn-store-password,,umountund weitere
- Die Beispiel-Liste enthält
- Dieser Ansatz wird seit etwa 10 Jahren verwendet und wird als Methode empfohlen, persönliche Befehlsnamen in
~/bin/sauber und ordentlich zu halten
2 Kommentare
Meinungen auf Hacker News
Nur vom Titel her dachte ich, das sei eine schreckliche Idee, aber tatsächlich gefällt sie mir ziemlich gut. Besonders mochte ich den Teil, in dem per Tab alle meine Tools aufgelistet werden.
In letzter Zeit hatte ich nicht viele Namespace-Kollisionen, und es stimmt auch, dass mein technisches Gespür etwas nachgelassen hat, seit ich ins Management gewechselt bin. Mein Tech-Stack fühlt sich etwa 10 Jahre veraltet an; ich frage mich, wo ich anfangen sollte, um wieder auf den aktuellen Stand zu kommen.
Meine Methode ist, selbst Tools zu bauen, die mir das Leben erleichtern. Wenn es zum Beispiel in der Firma einen Webservice gibt, den ich oft für einfache Abfragen nutze, schaue ich, ob es eine API gibt, und schreibe eine CLI, um Alltagsaufgaben schneller zu erledigen. Nachdem ich sie so poliert habe, dass sie mir gefällt, teile ich sie mit dem Team, aber andere davon zu überzeugen, sie auszuprobieren, ist schwierig. Da ich sie aber jeden Tag selbst nutze, kümmert mich das nicht besonders.
Ziel war, neue Perspektiven zu sehen und über Trends mitreden zu können; ein Teil davon ist inzwischen auch in die Arbeit eingeflossen. Dadurch habe ich auch ein tieferes Verständnis für die älteren Komponenten bekommen.
Ich verstehe dieses Problem nicht so recht. Man muss sein
bin-Verzeichnis einfach an den Anfang von$PATHsetzen, nicht ans Ende. Um meine Befehle durchzusehen, führe ich einfachls ~/binaus.$0in einem Systempfad liegt, das kaputtgeht und eine frustrierende Debugging-Session beginnt.Am Ende ist es die Frage, welches Gift man wählt.
fzf-Autovervollständigung nutzen kann. In fish kann man zum Beispiel den ersten Buchstaben eines Befehls tippen und Tab drücken, umfzfzu öffnen.Dann kann man mit
,+Tab benutzerdefinierte Befehle schnell herausfiltern.ls ~/bindagegen erfordert für etwas, das man häufig tut, ziemlich viele Tastendrücke; oder man muss vielleicht erst mitls+mehrfach Pfeil nach oben die Autovervollständigung finden.ls ~/binist beim Tippen viel langsamer als,.Für dünne Wrapper um
gitverwende ich kurze benutzerdefinierte Befehlsnamen wieaa,st,di,dp,cm,le.Einer davon kollidiert tatsächlich mit einem Utility, das auf manchen Systemen standardmäßig installiert ist. Aber mein
bin-Verzeichnis steht in$PATHvor den Systemverzeichnissen, also gewinnt meins, und das kollidierende Tool interessiert mich nicht besonders. Wenn ein anderes für mich nützliches Tool mit meinem Tool kollidieren würde, würde ich diesem anderen Tool wahrscheinlich eher einen kollisionsfreien Alias geben, als mein eigenes Tool umzubenennen. Diese Zwei-Buchstaben-Tools sind einfach zu bequem.apt-get upgradeplötzlich Dwarf Fortress startet.https://askubuntu.com/questions/938606/dwarf-fortress-starti...
git-Aliasse sind meistens Zwei-Buchstaben-Kombinationen, die mitgbeginnen. Zum Beispiel istgsgit status.Aber manchmal brauche ich tatsächlich GhostScript. Für Dinge wie das Einbetten von Schriften in PDF-Dateien ist es hervorragend. Normalerweise verwende ich dann
env gs.j. Alsjavaauftauchte, wurde das ziemlich unterhaltsam. Ein Komma zu verwenden ist eine ziemlich interessante Idee.Trotzdem bin ich froh, dass ich nicht mit
kangefangen habe, wegen KDE :)Zum Beispiel sollte
mkfsmeiner Meinung nach alssys::mkfsoder ähnlich aufgerufen werden. Die Grenze zwischen Systembefehlen und Benutzerbefehlen kann auf verschiedene Arten gezogen werden und es wird Grauzonen geben, aber wenn ein Nutzer einen Befehl versehentlich ausführen kann, von dem er nicht einmal weiß, dass er existiert, und den er nie ausdrücklich installiert hat, dann sollte dieser Befehl nicht direkt im globalen Namespace sichtbar sein.Dazu gibt es eine verwandte Frage
Ich nutze überwiegend Windows und habe, ähnlich wie der Autor, mehrere Python-zentrierte CLI-Skripte erstellt und sie an einem Ort abgelegt, der
~/bin/entspricht. Wenn manpython.exeals Standardprogramm für die Erweiterung.pyfestlegt und.pyzu%pathext%hinzufügt, kann man von jedem Pfad aus einfachhelloeingeben, um~/bin/hello.pyauszuführen; ich nutze das hunderte Male am Tag. Inzwischen verwende ich öfter Linux, bin dort aber noch Anfänger und habe es nicht geschafft, dasselbe Muster nachzubauen. Unter Linux scheint es kein Konzept eines „zugeordneten Programms“ zu geben, sodass man eine.py-Datei nicht einfach aufrufen und die Shell sie mit Python ausführen lassen kann. Natürlich kann man dem Skriptchmod +xgeben, aber dann muss man in das Skript selbst einen Shebang einfügen, was sich unangenehm nach Hardcoding anfühlt. Was, wenn ich später ein.py-Skript nicht mit/usr/bin/python, sondern mit/usr/bin/nohtypausführen möchte? Außerdem habe ich auch keinen Weg gefunden, beim Aufruf des Skripts den.py-Teil wegzulassen. Ich will das Linux-Design nicht kritisieren und weiß, dass es viele Vorteile hat, aber ich möchte wirklichhello.pyaus dem$PATHalshelloausführenmy_pythonan und schreibe den Shebang als/usr/bin/env my_pythonWenn du einen prinzipielleren Ansatz willst, schau dir das Tool
update-alternativesan. Es bietet solche Abstraktionen allgemeiner an: https://linuxconfig.org/how-to-set-default-programs-using-up...Unter Linux, und eigentlich auf den meisten Plattformen außer Windows, haben Dateiendungen eine deutlich schwächere Bedeutung. Ob eine Datei ausführbar ist, wird bei jeder Art von ausführbarer Datei nicht durch die Endung bestimmt, sondern etwa durch das
+x-Flag. Dadurch kann man die Implementierungssprache ändern und den Aufrufer unverändert lassen. Die Endung.pyist vor allem für Module sinnvoll, die importiert und verwendet werden; bei einem ausführbaren Skript schaut man bei Bedarf auf den Shebang. Extern verteilte Skripte verwenden normalerweise#!/usr/bin/env python, während Skripte in Distributionspaketen etwa mit#!/usr/bin/pythonüberschrieben werden. Außerdem unterstützt der Shebang zwar keine mehreren Argumente, aber GNUenvbietet das Argument-S, mit dem man das nachbilden kann. Das Problem der Argumentlänge bleibt allerdings bestehen.pyweg. Es ist völlig in Ordnung, sie"hello"zu nennenMir fallen nicht wirklich Nachteile des Shebangs ein. Wenn du es wirklich mit einem anderen Interpreter ausführen willst, kannst du das explizit tun, etwa mit
"nohtyp hello". Wenn dich das trotzdem zu sehr stört, kannst du in deinen Shell-Startdateien Aliasse definieren. In bash ginge zum Beispielalias hello="python3 /path/to/hello.py". Wenn du willst, kannst du sogar ein kurzes Skript schreiben, das solche Aliasse automatisch für den Inhalt eines bestimmten Verzeichnisses erzeugtIn Shell-Skripten fügt man üblicherweise einen Shebang hinzu und macht die Datei ausführbar, wodurch das ausführbare Programm im Skript selbst deklariert wird. Man kann sich den Shebang als eine Art Dateiendung vorstellen. Wenn nach
chmod +x ./malware.pyein./malware.pynicht funktioniert, sollte man den Pfad prüfen, auf den der Shebang zeigt. Wenn der Interpreter ein Skript als normales Argument ausführen kann, lässt sich mit etwas wiexdg-open malware.pyein ähnliches Verhalten erzeugen. Das entspräche dem Doppelklick im Standard-Dateimanager. Als ich Linux als primäres Desktop-Betriebssystem genutzt habe, hatte ich einen Alias namensxop, aber ich habe ihn nur für Datendateien wie Bilder oder Dokumente verwendet, bei denen das Standardverhalten ohnehin passte. Das Standardprogramm für ausführbare Skripte auf den Interpreter zu setzen, würde ich nicht empfehlen. Standardmäßig möchte man Skripte vielleicht lieber in einem Editor öffnen, statt sie auszuführen. Ich haltexdg-openfür ein Tool aus der Gnome-Ecke, was aber nicht heißt, dass es auf anderen Desktops nicht nutzbar wäre; ich habe es auch unter Xubuntu verwendet. Wenn du wirklich alle Python-Dateien auch im GUI-Kontext standardmäßig ausführen willst, kannst du so eine Voreinstellung setzen, aberman xdg-openkönnte helfen. Noch einmal: Das ist kein guter Rat#!/usr/bin/env pythonDadurch wird das erste
pythonausgeführt, das im Pfad gefunden wird. Wenn du später nicht/usr/bin/python, sondern/usr/bin/nohtypausführen willst, kannst du in einem Verzeichnis, das vor/usr/bindurchsucht wird, einen symbolischen Linkpythonanlegen, der auf/usr/bin/nohtypzeigt. Zum Beispiel könntest du~/myCommandPreferencesan den Anfang von$PATHsetzenEine andere Möglichkeit, Konflikte im
$PATHzu vermeiden, ist, ausführbaren Dateien sehr lange Namen zu geben, die andere ausführbare Dateien kaum verwenden werden, und in derbashrckurze Aliasse dafür anzulegenAliasse wirken sich nicht auf ausführbare Dateien aus, die innerhalb von Skripten aufgerufen werden, und in meinen Skripten kann ich weiterhin die langen Namen referenzieren. Der Nachteil ist, dass man nicht dieselbe Nutzbarkeit der Tab-Vervollständigung bekommt, und genau die ist wirklich ziemlich gut. Außerdem kann es bei Skripten, die wie das Aktivierungsskript von Pythons
venvnicht als Unterprozess ausgeführt, sondernsourced werden müssen, weiterhin zu Konflikten kommen, aber solche Fälle sind seltenzshfunktioniert auch diese VervollständigungDie Methode, mit einem Komma zu beginnen, ist auch in der Community rund um Texterweiterungen/Textsubstitution eine verbreitete Technik
,Neulich habe ich in
~/.local/bin/nachgesehen und festgestellt, dass dort Dutzende ausführbarer Dateien liegen, an deren Ablage ich mich nicht erinnern konnteDie meisten waren pyside-bezogen, aber es gab auch andere Skripte. Ich musste sie einzeln öffnen, um mich daran zu erinnern, welche ich selbst geschrieben hatte und welche von anderen stammten. Wenn die Namen meiner Skripte mit einem Komma begonnen hätten, wäre das viel schneller gegangen, und es hätte mir auch geholfen, mich schon vor dem Öffnen daran zu erinnern, warum ich das jeweilige Skript erstellt hatte
~/.local/bin/für installierte Skripte gedacht; lokal selbst geschriebene legt man in~/bin/abIch verzichte. Man kann sein persönliches
binan den Anfang von$PATHsetzen und für verdeckte Programme/usr/binoder/binverwenden.Die Liste der personalisierten Tools lässt sich mit
~/bin/[Tab]anzeigen.Wenn mir das
grepdes Systems, etwa Solaris-grep, nicht gefällt und ich lieber mein bevorzugtes GNU-grepverwenden möchte, warum sollte ich es dann nicht einfachgrepnennen?Dass ich vor fünf Jahren auf diese Idee gestoßen bin, hat Ordnung in meine Sammlung von Shell-Tricks gebracht. Zusammen mit Aliassen und
~/binhabe ich über 50 Komma-Befehle, und mein Shell-Alltag läuft deutlich reibungsloser als in dem früheren Durcheinander.Wurde auch 2020 diskutiert: https://news.ycombinator.com/item?id=22778988 (90 Kommentare)
, macroexpand.Start all of your commands with a comma (2009) - https://news.ycombinator.com/item?id=31846902 - Juni 2022 (121 Kommentare)
Start all of your commands with a comma (2009) - https://news.ycombinator.com/item?id=22778988 - April 2020 (89 Kommentare)
Wie wäre es mit der Verwendung von
'_'?