Bash history expansion: !! और !$ का उपयोग कैसे करें
Bash में !! पिछली कमांड को दोहराता है और !$ अंतिम आर्गुमेंट देता है। इस गाइड में छह महत्वपूर्ण हिस्ट्री एक्सपेंशन और :p का उपयोग सीखें ताकि आप कमांड रन करने से पहले उसे देख सकें।
Bash history expansion क्या करता है
Bash history expansion आपके shell history से एक पुरानी command line को bash द्वारा run किए जाने से पहले फिर से बनाता है। !! पिछली command को दोहराता है। !$ पिछली command के अंतिम argument को insert करता है। यह substitution textual होता है और यह सबसे पहले होता है, bash द्वारा line को शब्दों में विभाजित करने से पहले, इसलिए जो वापस आता है वह वही exact characters होते हैं जो आपने पहली बार type किए थे।
छह forms लगभग वह सब कुछ कवर करते हैं जो आप एक server पर करेंगे:
!!पूरी पिछली line को दोहराता है, औरsudo !!इसे root के रूप में फिर से run करता है।!$पिछली line का अंतिम argument है।!*पिछली line के सभी arguments हैं।!nhistory entry number n को run करता है, और!-nवर्तमान स्थिति से पीछे की ओर गिनती करता है।!stringसबसे हालिया command को run करता है जोstringसे शुरू हुई थी।^old^newपिछली line को फिर से run करता है जिसमें पहलेoldकोnewसे बदल दिया जाता है।
नीचे दी गई हर चीज़ आपके अपने server पर एक interactive prompt पर type की जाती है। History expansion scripts में बंद रहता है, जिसे अंतिम section में समझाया गया है।
एक लंबा पाथ, जिसे केवल एक बार टाइप करना पड़े
यह वह स्थिति है जो अपना मूल्य स्वयं चुकाती है। आप एक release directory तैयार कर रहे हैं, और पाथ इतना लंबा है कि उसे दूसरी बार टाइप करने पर गलती होने की संभावना रहती है।
sudo mkdir -p /srv/www/app/releases/2026-08-07
sudo chown -R deploy:deploy !$
ls -ld !$
sudo -u deploy nano !$/config.envप्रत्येक लाइन को चलाने से पहले, bash उस लाइन को प्रिंट करता है जो expansion के बाद तैयार हुई है:
sudo chown -R deploy:deploy /srv/www/app/releases/2026-08-07वह echo आपकी जाँच है। कमांड का आउटपुट पढ़ने से पहले उसे पढ़ें, क्योंकि यह एकमात्र मौका है जब आप देख सकते हैं कि bash ने !$ का क्या अर्थ निकाला है।
यह श्रृंखला इसलिए काम करती है क्योंकि bash history में expanded लाइन को स्टोर करता है, न कि उस !$ को जिसे आपने टाइप किया था। इसलिए लाइन 3 अपनी अंतिम argument को expanded लाइन 2 से लेती है, और लाइन 4 उसे लाइन 3 से लेती है। लाइन 4 यह भी दिखाती है कि designator के बाद टेक्स्ट आ सकता है: !$/config.env वह पाथ बन जाता है जिसके अंत में /config.env जुड़ा है, क्योंकि word designator / पर रुक जाता है।
उसी session से एक और उदाहरण। फाइल को edit करने के बाद आप उस directory को list करना चाहते हैं जिसमें वह स्थित है:
ls -l !$:h:h एक head modifier है। यह पाथ से अंतिम घटक (component) को हटा देता है, वही काम जो dirname करता है। :t केवल अंतिम घटक को रखता है, :r extension को हटा देता है, और :e केवल extension को रखता है।
पिछले कमांड को !! और sudo !! के साथ दोहराएं
आप sudo भूल जाते हैं, और service manager यह सूचित करता है:
systemctl restart nginxFailed to restart nginx.service: Interactive authentication required.sudo !!Bash !! को पिछली लाइन के टेक्स्ट से बदल देता है, इसलिए shell sudo systemctl restart nginx चलाता है।
!! बिल्कुल पिछली लाइन होती है, चाहे वह लाइन कुछ भी हो। यहीं पर सामान्य दुर्घटना होती है। आपको लगता है कि पिछला कमांड वही था जो विफल हुआ था, लेकिन उसके बाद आपने cd, या history चलाया, या विफल कमांड दो लाइन पीछे था। sudo !! तब root privileges के साथ गलत कमांड चला देता है। जब आप निश्चित न हों तो पहले इसे print करें:
sudo !!:p:p विस्तारित लाइन को print करता है और उसे चलाता नहीं है। print की गई लाइन आपके history में जुड़ जाती है, इसलिए यदि वह सही दिखती है, तो अगली लाइन पर एक साधारण !! उसे चला देता है।
!$ के साथ पिछले argument का पुन: उपयोग करें
!$ पिछली पंक्ति का अंतिम शब्द है। यह वह रूप है जिसका आप सबसे अधिक उपयोग करेंगे, क्योंकि अंतिम शब्द आमतौर पर वह चीज़ होती है जिस पर आप काम कर रहे होते हैं: एक path या एक service का नाम।
sudo systemctl status nginx
sudo systemctl reload !$यहाँ दो बातें लोगों को आश्चर्यचकित करती हैं।
पहली, !$ अंतिम शब्द है, न कि वह अंतिम argument जिसे आप सोच रहे थे। यदि पिछली पंक्ति एक redirection पर समाप्त हुई है, तो अंतिम शब्द redirect target है:
sudo nginx -T > /tmp/nginx-dump.conf
less !$वह तो ठीक काम करता है। लेकिन journalctl -u nginx > /tmp/log.txt के बाद, !$ का मान /tmp/log.txt होता है, न कि nginx। Echo की गई पंक्ति को पढ़ें।
दूसरी, expansion पाठ्य (textual) होता है, इसलिए एक variable unexpanded रूप में वापस आता है। ls $HOME/backups के बाद, !$ आपको $HOME/backups वर्ण देता है, जिसे bash फिर एक सामान्य parameter के रूप में expand करता है। इस क्रम को याद रखें: history expansion, parameter expansion और $( ) के साथ command substitution से पहले चलता है, इसलिए यह कभी भी मान (values) नहीं देखता, केवल टेक्स्ट देखता है।
आस-पास के रूपों को जानना उपयोगी है। !^ पहला argument है, !:2 दूसरा है, और !:2-4 एक range है। !!:$, !$ लिखने का लंबा तरीका है।
यदि आप commit करने से पहले टेक्स्ट देखना चाहते हैं, तो Alt-. (या Esc और फिर .) दबाएं। Readline पिछली command के अंतिम argument को सीधे आपके prompt में डाल देता है, जहाँ आप इसे edit कर सकते हैं। उससे पिछली command के अंतिम argument पर वापस जाने के लिए इसे फिर से दबाएं। जब तक आप Enter नहीं दबाते, तब तक कुछ भी run नहीं होता।
!* का उपयोग करके सभी arguments को आगे बढ़ाएं
!* पिछले line के पहले शब्द को छोड़कर बाकी सभी शब्द हैं।
stat /srv/www/app/shared/config.env /srv/www/app/shared/secrets.env
sudo chmod 600 !*"पहले शब्द को छोड़कर" वाक्यांश का यहाँ वास्तविक अर्थ है। !* केवल word 0 को हटाता है और कुछ नहीं, इसलिए options paths के साथ बने रहते हैं। ls -l file1 file2 के बाद, !* का मान -l file1 file2 होता है, इसलिए sudo chmod 600 !* विफल हो जाता है, क्योंकि chmod को argument के रूप में -l प्राप्त होता है। शब्दों को शून्य से गिनें और एक slice लें: !!:2* का अर्थ है शब्द 2 से अंत तक।
यही समस्या sudo के साथ भी आती है। sudo chown deploy:deploy /srv/www/app के बाद, word 0 का मान sudo है और word 1 का मान chown है, इसलिए !* अगले command को chown deploy:deploy /srv/www/app सौंप देता है। आप शायद ही कभी ऐसा चाहते हैं।
!n और !-n का उपयोग करके स्थिति के अनुसार कमांड चुनें
history प्रत्येक प्रविष्टि के सामने एक संख्या के साथ सूची प्रिंट करता है।
history 5 512 sudo nginx -t
513 sudo systemctl reload nginx
514 ss -tulpn
515 sudo tail -f /var/log/nginx/error.log
516 history 5!513 प्रविष्टि 513 को फिर से चलाता है। !-2 वर्तमान में टाइप की जा रही लाइन से दो लाइन पीछे की प्रविष्टि को चलाता है, इसलिए !-1 और !! का अर्थ एक ही है।
उपयोग करने से पहले संख्याओं की तुरंत जाँच करें। !-2 हर बार जब आप कुछ भी चलाते हैं, तो किसी नई जगह पर इंगित करता है, जिसमें बिना सोचे-समझे चलाया गया ls भी शामिल है। निरपेक्ष संख्याएँ एक सत्र के भीतर स्थिर रहती हैं, लेकिन वे उसी बॉक्स पर दूसरे सत्र में समान संख्याएँ नहीं होती हैं, और आपके अगले लॉगिन द्वारा हिस्ट्री फ़ाइल को वापस पढ़ने के बाद वे समान नहीं रहती हैं। कल याद की गई संख्या आज एक अलग कमांड की ओर इशारा करती है।
!string prefix के साथ कमांड को दोबारा चलाएं
!string उस सबसे हालिया कमांड को चलाता है जो string से शुरू होता है।
!ssयह ऊपर दी गई सूची से ss -tulpn को दोबारा चलाता है, जो Linux सर्वर पर कौन से पोर्ट खुले हैं में वर्णित लिसनिंग सॉकेट चेक है। !?string? कमांड लाइन में कहीं भी मैच ढूंढता है, न कि केवल शुरुआत में। यह तब उपयोगी होता है जब आपको कमांड का नाम याद न हो लेकिन उसका कोई आर्गुमेंट याद हो।
प्रीफिक्स को लंबा रखें। !s, ss, sudo, systemctl या shutdown में से जो भी सबसे हाल ही में चला होगा, उसे मैच कर लेगा, और आपको तब तक पता नहीं चलेगा कि कौन सा कमांड चला है जब तक वह निष्पादित न हो जाए। !string:p कमांड को चलाए बिना मैच को प्रिंट करता है। यदि कुछ भी मैच नहीं होता है, तो bash bash: !ss: event not found प्रिंट करता है और कुछ भी नहीं चलाता है, जो कि एक सुरक्षित परिणाम है।
^old^new का उपयोग करके एक टाइपो ठीक करें
sudo systemctl status ngnixUnit ngnix.service could not be found.^ngnix^nginxशेल पिछली लाइन को फिर से चलाता है जिसमें पहला ngnix, nginx से बदल दिया जाता है। केवल पहला मैच ही बदला जाता है। हर मैच को बदलने के लिए, लंबे फॉर्म !!:gs/ngnix/nginx/ का उपयोग करें, जहाँ s का अर्थ है प्रतिस्थापित (substitute) करना और g का अर्थ है इसे पूरी लाइन में लागू करना।
रन करने से पहले एक्सपेंशन (expansion) को प्रिंट करें
दो आदतें उस दुर्घटना को रोकती हैं जहाँ एक एक्सपेंशन कुछ ऐसा चला देता है जिसका आपने इरादा नहीं किया था।
पहली आदत :p है, जिसे आप पहले ही देख चुके हैं। इसे किसी एक्सपेंशन के अंत में जोड़ें और bash उसे चलाने के बजाय उसका परिणाम प्रिंट कर देता है: !!:p, या !systemctl:p। प्रिंट की गई लाइन आपकी हिस्ट्री में चली जाती है, इसलिए बाद में !! चलाने पर वही कमांड रन हो जाती है जिसे आपने अभी पढ़ा है।
दूसरी आदत अधिक प्रभावी है, क्योंकि यह बिना कुछ याद रखे हर एक्सपेंशन पर लागू होती है:
shopt -s histverifyइस लाइन को ~/.bashrc में डालें। histverify सेट होने पर, Enter दबाने पर एक्सपेंशन रन नहीं होता है। Bash एक्सपेंडेड लाइन को वापस आपके प्रॉम्प्ट में लिख देता है ताकि आप उसे पढ़ सकें और एडिट कर सकें, और फिर उसे रन करने के लिए आपको दूसरी बार Enter दबाना पड़ता है। इसमें एक अतिरिक्त की-स्ट्रोक लगता है और यह दुर्घटनाओं की पूरी श्रेणी को समाप्त कर देता है। इसके लिए readline की आवश्यकता होती है, इसलिए यह केवल इंटरैक्टिव प्रॉम्प्ट पर काम करता है, कहीं और नहीं।
Ctrl-R काम करने का दूसरा तरीका है, और यह कभी भी किसी चीज को एक्सपैंड नहीं करता है। Ctrl-R दबाएं और कमांड का कुछ हिस्सा टाइप करें। प्रॉम्प्ट बदलकर reverse-i-search प्रॉम्प्ट हो जाता है और टाइप करते ही सबसे हालिया मैच दिखाता है। पुराने मैचों पर वापस जाने के लिए फिर से Ctrl-R दबाएं। Enter दबाने पर दिखाई जा रही लाइन रन हो जाती है। Ctrl-G सर्च को रद्द कर देता है और आपका मूल प्रॉम्प्ट वापस ले आता है। लेफ्ट एरो की (left arrow key) सर्च को समाप्त कर देती है और मैच हुई लाइन को एडिटिंग के लिए आपके प्रॉम्प्ट में छोड़ देती है।
जब आप कमांड को पहले देखना चाहते हैं, तो Ctrl-R का उपयोग करें। जब कमांड एक लाइन पुरानी हो और आप उसे अभी भी स्क्रीन पर पढ़ सकते हैं, तो !! और !$ का उपयोग करें।
echo "done!" कमांड 'event not found' क्यों दिखाती है
echo "deploy done!"bash: !": event not foundHistory expansion, quoting के हल होने से पहले चलती है, और double quotes ! character को सुरक्षित नहीं रखते हैं। केवल single quotes और backslash ही ऐसा कर सकते हैं। इसलिए echo 'deploy done!' वही प्रिंट करता है जिसकी आप अपेक्षा करते हैं। Backslash भी expansion को रोकता है, लेकिन double quotes के अंदर bash backslash को output में ही छोड़ देता है, इसलिए single quotes ही सबसे सही समाधान हैं।
यह समस्या passwords के साथ सबसे अधिक होती है, क्योंकि एक मजबूत password में अक्सर ! होता है। mysql -u app -p"S3cret!pass" जैसी कमांड या तो 'event-not-found' error के साथ विफल हो जाती है, या यदि कोई history entry उससे मेल खाती है, तो चुपचाप एक अलग string भेज देती है। Single quotes का उपयोग करें, या बेहतर होगा कि tool को आपसे password पूछने दें ताकि secret कभी command line तक पहुँचे ही नहीं। यह आदत आपकी account hygiene का हिस्सा होनी चाहिए: keys और passwords को नए server पर कैसे handle किया जाए, इसके लिए नए VPS पर शुरुआती दस मिनट देखें।
यदि आप ! characters से भरे text के block को paste करने वाले हैं, तो उस session के लिए expansion को set +H के साथ बंद कर दें, और काम पूरा होने पर set -H के साथ वापस चालू कर लें।
HISTSIZE, HISTFILESIZE और आपकी history कहाँ रखी जाती है
ये दो variables हैं, और लोग इनके नाम मिलते-जुलते होने के कारण अक्सर भ्रमित हो जाते हैं।
HISTSIZEयह निर्धारित करता है कि running shell memory में कितनी commands रखती है।HISTFILESIZEयह निर्धारित करता है कि disk पर मौजूद file में कितनी lines रखी जाती हैं,~/.bash_historyजब तक किHISTFILEकुछ और न कहे।
जब shell exit होती है, तब file लिखी जाती है, और उस समय इसे HISTFILESIZE lines तक truncate कर दिया जाता है। Ubuntu का default ~/.bashrc इसे 1000 और 2000 पर set करता है। जाँचें कि आपके system में वर्तमान में क्या values हैं:
grep HIST ~/.bashrc
echo "$HISTSIZE $HISTFILESIZE $HISTFILE"यदि आपकी !string searches में वे commands नहीं मिलतीं जो आपने run की थीं, तो इन दोनों values को बढ़ा दें। 10000 और 20000 जैसी values सामान्य हैं और इनका कोई खास performance cost नहीं होता, क्योंकि file plain text में होती है। negative value का अर्थ है कि कोई limit नहीं है।
जब आप एक सप्ताह बाद किसी server पर वापस आते हैं, तो timestamps बहुत काम आते हैं:
export HISTTIMEFORMAT='%F %T 'history प्रत्येक entry के सामने date और time print करता है, क्योंकि bash file में प्रत्येक command से पहले epoch seconds वाली एक comment line लिखना शुरू कर देता है।
एक आम शिकायत यह है कि जब आप एक से अधिक terminal का उपयोग करते हैं, तो history गायब हो जाती है। प्रत्येक shell अपनी list memory में रखती है और exit होने पर उसे लिखती है, इसलिए histappend के बिना, जो shell सबसे अंत में बंद होती है, वह दूसरों द्वारा save की गई history को overwrite कर देती है। दो settings इसे ठीक करती हैं:
shopt -s histappend
export PROMPT_COMMAND='history -a'histappend shell को file को replace करने के बजाय अपनी list को file के अंत में जोड़ने (append) के लिए कहता है। history -a प्रत्येक prompt के बाद नई lines को append करता है, इसलिए यदि कोई session cleanly बंद होने के बजाय kill हो जाता है, तब भी उसकी commands सुरक्षित रहती हैं। Ubuntu का default ~/.bashrc पहले से ही histappend set करता है। यह तब और अधिक महत्वपूर्ण हो जाता है जब आप अधिक machines चलाते हैं, क्योंकि history प्रति user प्रति machine store होती है, इसलिए जब आप एक workstation से कई servers manage कर रहे होते हैं, तो हो सकता है कि जो !$ आप ढूँढ रहे हैं, वह किसी दूसरे host पर हो।
Bash history से secrets को बाहर रखना
HISTCONTROL यह निर्धारित करता है कि कौन सी lines को save किया जाएगा।
ignorespacespace से शुरू होने वाली किसी भी line को हटा देता है।ignoredupsपिछली line के समान होने वाली line को हटा देता है।ignorebothऊपर दिए गए दोनों कार्य करता है।erasedupssave की जा रही line की हर पुरानी copy को हटा देता है।
export HISTCONTROL=ignorebothजब ignorespace active होता है, तो एक leading space कमांड को in-memory list से बाहर रखता है, इसलिए वह file तक कभी नहीं पहुँचती। इस पर भरोसा करने से पहले echo "$HISTCONTROL" के साथ इसकी value की जाँच करें। Ubuntu का default user .bashrc, ignoreboth को set करता है, लेकिन root shell या minimal image में यह unset रह सकता है। ऐसी स्थिति में leading space का कोई प्रभाव नहीं पड़ता और line सामान्य रूप से store हो जाती है।
यह स्पष्ट समझें कि यह क्या सुरक्षित रखता है। यह line ~/.bash_history से बाहर रहती है। process के चलने के दौरान यह ps output में दिखाई देती है, इसलिए server पर मौजूद कोई भी अन्य user इसे वहाँ पढ़ सकता है। sudo सिस्टम log में चलाए गए कमांड को record करता है। history file plain text होती है, इसलिए इसे mode 600 पर रखें और याद रखें कि जो कोई भी आपकी home directory पढ़ सकता है, वह आपके पिछले कुछ हजार कमांड भी पढ़ सकता है।
यदि कोई संवेदनशील जानकारी पहले से ही list में है, तो उस entry को हटा दें और file को फिर से लिखें:
history
history -d 517
history -whistory -d उस entry को memory से हटा देता है, और history -w वर्तमान list को file पर लिख देता है। history -c पूरी list को clear कर देता है। HISTIGNORE secrets के बजाय शोर (noise) के लिए संबंधित विकल्प है: HISTIGNORE='ls:pwd:history:clear' उन lines को list से बाहर रखता है ताकि आपकी searches में केवल उपयोगी परिणाम मिलें।
शेल स्क्रिप्ट में history expansion काम क्यों नहीं करता है
History expansion केवल interactive shells के लिए होता है। एक स्क्रिप्ट non-interactive shell में चलती है, जहाँ history list सक्षम नहीं होती और expansion बंद रहता है, इसलिए !! और !$ लाइन में सामान्य टेक्स्ट के रूप में ही रहते हैं। स्क्रिप्ट के अंदर sudo !! का उपयोग करने पर sudo एक ऐसी कमांड चलाने की कोशिश करता है जिसका नाम शाब्दिक रूप से !! है, और यह विफल हो जाता है।
आप जिस शेल में काम कर रहे हैं, उसे जाँचें:
echo $-आउटपुट वर्तमान option flags का समूह होता है, जैसे कि himBHs। i का अर्थ है कि शेल interactive है और H का अर्थ है कि history expansion सक्षम है। इसी लाइन को स्क्रिप्ट के अंदर चलाएं, तो इनमें से कोई भी अक्षर वहां नहीं होगा।
यह आपके शेल कार्य के दो हिस्सों के बीच की विभाजक रेखा है। प्रॉम्प्ट पर, !$ और Ctrl-R उन कमांड्स पर कीस्ट्रोक्स बचाते हैं जिन्हें आप देख सकते हैं। एक फाइल में, आप चीजों को नाम देते हैं: पाथ को एक वेरिएबल में रखें, या command substitution के साथ आउटपुट कैप्चर करें। जो स्क्रिप्ट आपकी व्यक्तिगत हिस्ट्री पर निर्भर होगी, वह उसे चलाने वाले अगले व्यक्ति के लिए अलग व्यवहार करेगी, जो कि स्क्रिप्ट के मूल उद्देश्य के विपरीत है।
इसी कारण से, इस पेज पर दिया गया प्रत्येक उदाहरण लाइव प्रॉम्प्ट पर टाइप करने के लिए है। इनमें से कोई भी चीज .sh फाइल में पेस्ट करने पर वैसा व्यवहार नहीं करेगी।
FAQ
Bash में !! का क्या अर्थ है?
!! पिछली कमांड लाइन के पूरे टेक्स्ट को विस्तार (expand) देता है, इसलिए sudo !! आपकी पिछली कमांड को root के रूप में दोबारा चलाता है। यह विस्तार टेक्स्ट आधारित है और bash द्वारा लाइन को पार्स करने से पहले होता है, और bash इसे चलाने से ठीक पहले पूरी लाइन को प्रिंट करता है। यदि आप सुनिश्चित नहीं हैं कि पिछली लाइन क्या थी, तो पहले sudo !!:p टाइप करें। :p बिना चलाए विस्तार को प्रिंट करता है, और यह प्रिंट की गई लाइन को आपकी history में जोड़ देता है, ताकि बाद में !! उसे चला सके।
मैं पिछली कमांड के अंतिम argument का पुन: उपयोग कैसे करूँ?
!$ का उपयोग करें। sudo mkdir -p /srv/www/app/releases के बाद, लाइन ls -ld !$ बदलकर ls -ld /srv/www/app/releases हो जाती है। यह लाइन के अंतिम शब्द को लेता है, इसलिए अंत में दिया गया redirection target भी अंतिम शब्द माना जाता है। आप इसमें टेक्स्ट भी जोड़ सकते हैं: !$/config.env पाथ में जुड़ जाता है, क्योंकि word designator / पर रुक जाता है। इसका इंटरैक्टिव विकल्प Alt-. है, जो आपके प्रॉम्प्ट में वही टेक्स्ट डाल देता है ताकि Enter दबाने से पहले आप उसे पढ़ सकें।
जब मेरे टेक्स्ट में विस्मयादिबोधक चिह्न (exclamation mark) होता है, तो bash "event not found" क्यों कहता है?
Double quotes, ! को history expansion से नहीं बचाते, इसलिए echo "done!" bash को history event खोजने के लिए मजबूर करता है और bash: !": event not found प्रिंट करता है। Single quotes इसे सुरक्षित रखते हैं, इसलिए echo 'done!' लिखें। एक backslash भी विस्तार को रोकता है, लेकिन double quotes के अंदर bash backslash को आउटपुट में छोड़ देता है। ! युक्त लंबे ब्लॉक को पेस्ट करने के लिए, set +H के साथ सेशन के लिए expansion को बंद कर दें।
!! और !$ मेरी shell script में काम क्यों नहीं करते?
History expansion केवल इंटरैक्टिव shells में सक्षम होती है। एक स्क्रिप्ट non-interactively चलती है, इसलिए shell कभी भी history list नहीं बनाती, और !! लाइन में साधारण टेक्स्ट के रूप में रह जाता है। यह देखने के लिए कि आप किस shell में हैं, echo $- चलाएँ: एक इंटरैक्टिव shell i और H सहित flags प्रिंट करती है, और एक स्क्रिप्ट में इनमें से कुछ भी नहीं दिखता। स्क्रिप्ट में, इसके बजाय variable या command substitution का उपयोग करें।
मैं अपने bash history से पासवर्ड को कैसे दूर रखूँ?
~/.bashrc में HISTCONTROL=ignorespace या HISTCONTROL=ignoreboth सेट करें, फिर कमांड को एक single space के साथ शुरू करें और यह कभी सेव नहीं होगा। पहले echo "$HISTCONTROL" के साथ मान की पुष्टि करें, क्योंकि यदि यह unset है तो leading space का कोई प्रभाव नहीं पड़ेगा। यह केवल लाइन को ~/.bash_history से बाहर रखता है। कमांड चलते समय ps में दिखाई देती है, और sudo लॉग करता है कि उसने क्या निष्पादित किया। यदि कोई secret पहले से सेव हो गया है, तो history के साथ उसका नंबर ढूँढें, फिर फाइल को फिर से लिखने के लिए history -w के साथ history -d <number> चलाएँ।