हर कमांड को कॉमा से शुरू करें (2009)
(rhodesmill.org)- Unix उपयोगकर्ता जब
~/bin/में निजी scripts रखकर उसेPATHमें जोड़ते हैं, तो छोटे command names नई system commands से टकरा सकते हैं - Debian/Ubuntu जैसे बहुत सारे commands देने वाले environments में जोखिम और बढ़ जाता है; उदाहरण वाले Ubuntu laptop के
/usr/bincommands की गिनती 21,733 निकली - निजी commands के आगे कॉमा (
,) लगाने पर shell और tools इसे सामान्य filename character की तरह treat करते हैं, फिर भी system commands से अलग पहचानना आसान रहता है - कॉमा Shift के बिना type किया जा सकता है, और shell में मजबूत meaning रखने वाले parentheses, backslash, colon, backtick, single quote, slash और dot की तुलना में collision की गुंजाइश कम होती है
,के बाद Tab दबाने पर निजी commands की list तुरंत देखी जा सकती है, जिससे~/bin/command names को साफ-सुथरा रखना आसान होता है
निजी command names क्यों टकराते हैं
- कई Unix users home directory में
~/bin/बनाते हैं और उसेPATHमें जोड़कर निजी सुविधा commands और shell scripts इस्तेमाल करते हैं - समस्या यह है कि निजी script names आमतौर पर छोटे lowercase combinations होते हैं, इसलिए वे default system commands जैसे दिखने लगते हैं
- अगर Linux distribution कोई नया command जोड़ता है, तो उसका नाम संयोग से किसी मौजूदा निजी command जैसा हो सकता है
- Debian-परिवार के environments में उपलब्ध commands की संख्या ज्यादा होने से यह समस्या ज्यादा वास्तविक लगती है
- उदाहरण वाले Ubuntu laptop में
/usr/binके ठीक नीचे commands गिनने पर21,733मिलते हैं apt-file search -x '^/usr/bin/[^/]*$' | wc -l
- उदाहरण वाले Ubuntu laptop में
कॉमा prefix के फायदे
- समाधान यह है कि निजी command names को ऐसे रूप में बदला जाए जो type करने में आसान हो, लेकिन system command name के रूप में आम तौर पर चुना न जाता हो
- typing सुविधा का मानदंड है Shift key का इस्तेमाल न करना, और इस शर्त को पूरा करते हुए सुरक्षित characters बहुत ज्यादा नहीं हैं
- lowercase letters पहले से ही system commands में आम हैं
- parentheses, backslash, colon, backtick और single quote का shell में special meaning होता है
- slash directory separator है, इसलिए filename में नहीं आ सकता
- dot filename की शुरुआत में hidden file को दर्शाता है, और दूसरी जगहों पर भी extension अलग करने के लिए अक्सर इस्तेमाल होता है
- बचा हुआ विकल्प सरल कॉमा (
,) है, और आसपास के tools व shell कॉमा को filename के अंदर सामान्य character की तरह treat करते हैं - हर निजी command में prefix के रूप में कॉमा लगाने से वे system commands से साफ अलग हो जाते हैं और name collisions से बचना आसान होता है
- Tab completion के साथ इस्तेमाल करने पर
,type करने के बाद निजी commands की list तुरंत देखी जा सकती है- उदाहरण list में
,complete-scp,,complete-ssh,,coreoff,,coreon,,find,,go-thpgp,,gr,,hss,,mount-thpgp,,mount-twt,,range,,svn-store-password,,umountआदि शामिल हैं
- उदाहरण list में
- यह तरीका करीब 10 साल से इस्तेमाल किया जा रहा है और निजी
~/bin/command names को साफ-सुथरे ढंग से व्यवस्थित रखने के तरीके के रूप में recommend किया जाता है
2 टिप्पणियां
Hacker News टिप्पणियाँ
सिर्फ़ शीर्षक देखकर लगा था कि यह एक भयानक आइडिया होगा, लेकिन असल में यह काफ़ी पसंद आया। खासकर Tab के ज़रिए अपने सारे tools को लिस्ट करने वाला हिस्सा अच्छा लगा।
हाल के दिनों में मुझे namespace conflict ज़्यादा नहीं झेलने पड़े हैं, और management role में जाने के बाद मेरी technical sharpness थोड़ी ढीली पड़ी है, यह भी सच है। मेरा tech stack लगभग 10 साल पुराना महसूस होता है, इसलिए सोचता हूँ कि फिर से up-to-date होने की शुरुआत कहाँ से करूँ
मेरा तरीका यह है कि मैं ऐसे tools खुद बनाता हूँ जो मेरी ज़िंदगी आसान करें। उदाहरण के लिए, अगर कंपनी में कोई web service साधारण lookup के लिए बार-बार इस्तेमाल होती है, तो मैं देखता हूँ कि उसका API है या नहीं, और रोज़मर्रा के काम तेज़ करने के लिए CLI लिख लेता हूँ। उसे अपनी पसंद के हिसाब से polish करने के बाद टीम के साथ share करता हूँ, लेकिन दूसरों को उसे अपनाने के लिए मनाना मुश्किल होता है। फिर भी मैं उसे हर दिन इस्तेमाल करता हूँ, इसलिए ज़्यादा परवाह नहीं करता
मकसद यह था कि नए नज़रिए दिखें और trends पर बातचीत कर सकूँ, और उनमें से कुछ अब काम में भी आ चुके हैं। इससे पुराने components को भी और गहराई से समझने में मदद मिली
मुझे सच में समझ नहीं आता कि यहाँ समस्या क्या है। अपना
bindirectory बस$PATHके अंत में नहीं, शुरुआत में रख दो। अपने commands देखना हों तो बसls ~/binचला लो$0system path में है, और वह टूट जाता है, जिसके बाद परेशान करने वाली debugging शुरू हो सकती है।आख़िर में यह बस इस बात का सवाल है कि कौन-सा ज़हर चुनना है
fzfautocomplete इस्तेमाल किया जा सकता है। उदाहरण के लिए fish में command का पहला अक्षर टाइप करके Tab दबाओ तोfzfखुल सकता है।तब सिर्फ़
,+Tab से custom commands जल्दी filter किए जा सकते हैं। इसके मुकाबलेls ~/binमें, जबकि यह काम अक्सर किया जाता है, टाइप करने के लिए काफ़ी ज़्यादा लिखना पड़ता है, या फिरls+ऊपर वाला arrow कई बार दबाकर पहले autocomplete तक पहुँचना पड़ सकता हैls ~/bin,,की तुलना में टाइप करने में बहुत धीमा हैमैं
gitके लिए एक thin wrapper मेंaa,st,di,dp,cm,leजैसे छोटे custom command names इस्तेमाल करता हूँ।इनमें से एक सचमुच किसी utility से टकराता है जो कुछ systems पर default install होती है। फिर भी मेरा
bindirectory system directories से पहले$PATHमें है, इसलिए मेरी command जीत जाती है, और उस टकराने वाले tool में मेरी ख़ास दिलचस्पी भी नहीं है। अगर कोई और उपयोगी tool मेरे tool से टकराए, तो मैं शायद अपने tool का नाम बदलने के बजाय उस दूसरे tool को कोई non-conflicting alias दे दूँ। ये दो-अक्षरी tools बहुत सुविधाजनक हैंapt-get upgradeDwarf Fortress चला दे।https://askubuntu.com/questions/938606/dwarf-fortress-starti...
gitaliases ज़्यादातरgसे शुरू होने वाले दो-अक्षरी combinations होते हैं। जैसेgsका मतलबgit statusहै।लेकिन कभी-कभी सच में GhostScript की ज़रूरत पड़ती है। जैसे PDF files में fonts embed करते समय यह बहुत बढ़िया है। आम तौर पर तब मैं
env gsइस्तेमाल करता हूँjसे शुरू होती हैं।javaआने पर यह काफ़ी मज़ेदार हो गया था। comma इस्तेमाल करना काफ़ी दिलचस्प idea है।फिर भी अच्छा है कि मैंने
kसे शुरू नहीं किया, KDE की वजह से :)उदाहरण के लिए, मेरे हिसाब से
mkfsकोsys::mkfsजैसी किसी चीज़ के रूप में चलाना चाहिए। system commands और user commands के बीच की रेखा कई तरीकों से तय की जा सकती है, और कुछ धुंधले हिस्से भी होंगे, लेकिन अगर कोई command ऐसी है जिसे user न तो जानता है और न ही उसने explicitly install किया है, फिर भी वह गलती से चल सकती है, तो उसे global namespace में सीधे expose नहीं होना चाहिएएक संबंधित सवाल है
मैं ज़्यादातर Windows इस्तेमाल करता हूँ, और लेखक की तरह Python-केंद्रित कई CLI scripts बनाकर उन्हें
~/bin/के समकक्ष किसी जगह रखता हूँ। अगरpython.exeको.pyextension के लिए default program सेट कर दिया जाए और.pyको%pathext%में जोड़ दिया जाए, तो किसी भी path से सिर्फhelloटाइप करके~/bin/hello.pyचला सकता हूँ, और मैं ऐसा दिन में सैकड़ों बार करता हूँ। आजकल Linux ज़्यादा इस्तेमाल कर रहा हूँ, लेकिन अभी भी नया हूँ इसलिए वैसा ही सेटअप नहीं बना पाया। Linux में शायद “associated program” जैसा concept नहीं है, इसलिए.pyfile को सीधे call करके shell से Python में run नहीं करा सकता। हाँ, script परchmod +xदे सकता हूँ, लेकिन तब script में shebang डालना पड़ता है, जो hardcoding जैसा लगता है और असुविधाजनक है। बाद में अगर.pyscript को/usr/bin/pythonकी जगह/usr/bin/nohtypसे चलाना चाहूँ तो? और script को call करते समय.pyहिस्सा छोड़ने का तरीका भी नहीं मिला। Linux की design की आलोचना नहीं कर रहा, उसके बहुत फायदे हैं, लेकिन मैं सचमुच$PATHमें मौजूदhello.pyकोhelloकी तरह चलाना चाहता हूँmy_pythonsymbolic link रखिए, और shebang को/usr/bin/env my_pythonलिखिएअगर ज़्यादा सिद्धांतपरक तरीका चाहिए तो
update-alternativestool देखिए। यह इस तरह की abstraction को और सामान्य रूप से देता है: https://linuxconfig.org/how-to-set-default-programs-using-up...Linux में, और वास्तव में Windows को छोड़ अधिकांश platforms पर, file extension का महत्व बहुत कम होता है। किसी भी तरह की executable file का चलना extension से नहीं बल्कि
+xflag जैसी चीज़ों से तय होता है। इसकी वजह से implementation language बदलकर दोबारा लिखने पर भी calling side नहीं टूटती।.pyextension का अर्थ import की जाने वाली modules के लिए होता है; executable scripts के लिए ज़रूरत पड़ने पर shebang देखा जाता है। बाहरी distribution scripts आम तौर पर#!/usr/bin/env pythonइस्तेमाल करती हैं, और distribution package में शामिल scripts को अक्सर#!/usr/bin/pythonआदि से overwrite किया जाता है। shebang कई arguments support नहीं करता, लेकिन GNUenvइसे नकल करने के लिए-Sargument देता है। हालांकि argument length की समस्या फिर भी रहती है.pyहटा दीजिए। उसे"hello"कहना पूरी तरह ठीक हैshebang का कोई खास नुकसान याद नहीं आता। अगर सचमुच किसी दूसरे interpreter से चलाना हो, तो
"nohtyp hello"की तरह explicitly चला सकते हैं। फिर भी अगर यह बहुत खलता है, तो shell startup file में alias define कर सकते हैं। उदाहरण के लिए bash मेंalias hello="python3 /path/to/hello.py"जैसा। चाहें तो किसी directory की contents के लिए ऐसे aliases अपने-आप बनाने वाली छोटी script भी लिख सकते हैंshell scripts में आम तौर पर shebang जोड़कर और file को executable बनाकर, executable को script के भीतर ही घोषित किया जाता है। shebang को एक तरह के file extension की तरह समझ सकते हैं।
chmod +x ./malware.pyके बाद./malware.pyकाम न करे, तो shebang जिस path की ओर इशारा कर रहा है उसे देखिए। अगर interpreter script को सामान्य argument की तरह चला सकता है, तोxdg-open malware.pyजैसी तरह से भी मिलता-जुलता व्यवहार बनाया जा सकता है। यह default file manager में double-click करने जैसा होगा। Linux को मुख्य desktop OS की तरह इस्तेमाल करते समय मैंनेxopनाम का alias रखा था, लेकिन उसे सिर्फ image या document जैसी data files के लिए इस्तेमाल किया, जहाँ default behavior पहले से सही होता है। executable scripts के लिए default program को interpreter बनाना recommend नहीं करूँगा। हो सकता है आप default रूप से script चलाने के बजाय उसे editor में खोलना चाहें। मुझे लगता हैxdg-openGnome की ओर का tool है, लेकिन इसका मतलब यह नहीं कि दूसरे desktops पर इसका उपयोग नहीं हो सकता; मैंने इसे Xubuntu में भी इस्तेमाल किया है। अगर आप सचमुच चाहते हैं कि सभी Python files GUI context में भी default रूप से run हों, तो वह default सेट किया जा सकता है, लेकिनman xdg-openमददगार हो सकता है। फिर भी, यह अच्छी सलाह नहीं है#!/usr/bin/env pythonहैइससे path में सबसे पहले मिलने वाला
pythonचलाया जाएगा। अगर बाद में आप/usr/bin/pythonकी जगह/usr/bin/nohtypसे चलाना चाहें, तो/usr/binसे पहले search होने वाली directory में/usr/bin/nohtypकी ओर इशारा करताpythonsymbolic link बना सकते हैं। उदाहरण के लिए,~/myCommandPreferencesको$PATHके आगे जोड़ सकते हैं$PATHconflict से बचने का दूसरा तरीका यह है कि बहुत लंबा executable name रखा जाए, जिसे किसी और executable के इस्तेमाल करने की संभावना कम हो, औरbashrcमें उसके लिए छोटा alias रखा जाएalias का असर scripts के भीतर call की जाने वाली executables पर नहीं पड़ेगा, और मैं अपनी scripts में लंबे नाम से ही refer करता रह सकता हूँ। कमी यह है कि वैसी tab autocomplete usability नहीं मिलती, और वह हिस्सा सच में काफ़ी बढ़िया है। Python की
venvactivation script जैसी scripts, जिन्हें child process की तरह चलाने के बजायsourceकिया जाना चाहिए, उनमें फिर भी conflict हो सकता है, लेकिन ऐसे मामले कम होते हैंzshमें वह autocomplete भी हो जाती हैcomma से शुरू करने का तरीका text expander/text replacement community में भी आम है
,से शुरू होते हैंहाल ही में
~/.local/bin/देखते समय मुझे दर्जनों executables मिले जिन्हें मैंने वहाँ रखा हो, ऐसा मुझे याद नहीं थाउनमें ज़्यादातर pyside से जुड़े थे, लेकिन कुछ दूसरी scripts भी थीं। कौन-सी script मैंने खुद लिखी थी और कौन-सी किसी और ने बनाई थी, यह याद करने के लिए मुझे एक-एक खोलकर देखना पड़ा। अगर मेरी scripts के नाम comma से शुरू होते, तो यह बहुत जल्दी हो जाता, और हर script क्यों बनाई थी यह भी उसे खोले बिना याद करने में मदद मिलती
~/.local/bin/installed scripts के लिए होता है, और locally खुद लिखी गई चीज़ें~/bin/में रखी जाती हैंमैं ऐसा नहीं करूँगा। अपना personal
bin$PATHके आगे रख लें, और जब किसी shadow हुए प्रोग्राम को refer करना हो तो/usr/binया/binइस्तेमाल किया जा सकता हैpersonalized tools की सूची
~/bin/[Tab]से दिखाई जा सकती हैअगर मुझे system का
grep, जैसे Solarisgrep, पसंद नहीं है और मैं अपनी पसंद का GNUgrepइस्तेमाल करना चाहता हूँ, तो उसे बसgrepही क्यों न रहने दूँ?5 साल पहले यह आइडिया देखने की वजह से मैं अपने shell tricks के संग्रह में व्यवस्था ला सका। aliases और
~/binको मिलाकर अब comma commands 50 से ज़्यादा हैं, और पहले की उलझी हुई हालत की तुलना में shell life बहुत ज़्यादा smooth हो गई है2020 में भी इस पर चर्चा हुई थी: https://news.ycombinator.com/item?id=22778988 (90 comments)
, macroexpandका परिणाम भी हैअपने सभी commands को comma से शुरू करें (2009) - https://news.ycombinator.com/item?id=31846902 - जून 2022 (121 comments)
अपने सभी commands को comma से शुरू करें (2009) - https://news.ycombinator.com/item?id=22778988 - अप्रैल 2020 (89 comments)
'_'का इस्तेमाल करना कैसा रहेगा?