Bash history expansion: !! మరియు !$ ఎలా వాడాలి
!! చివరి commandను, !$ దాని చివరి argumentను మళ్లీ వాడతాయి. తెలుసుకోవాల్సిన 6 Bash history expansions, అలాగే అమలుకు ముందు చూపించే :p గురించి తెలుసుకోండి.
Bash history expansion ఏమి చేస్తుంది
Bash history expansion, bash కమాండ్ను అమలు చేయడానికి ముందు shell history నుంచి మునుపటి కమాండ్ లైన్ను పునర్నిర్మిస్తుంది. !! మునుపటి కమాండ్ను మళ్లీ అమలు చేస్తుంది. !$ మునుపటి కమాండ్లోని చివరి argument ను చేర్చుతుంది. ఈ substitution పాఠ్యరూపంలో జరుగుతుంది. Bash లైన్ను words గా విభజించడానికి ముందే ఇది జరుగుతుంది. అందువల్ల తిరిగి వచ్చే విషయం, మీరు మొదట టైప్ చేసిన ఖచ్చితమైన characters అవుతాయి.
మీరు server పై సాధారణంగా ఉపయోగించే దాదాపు అన్ని సందర్భాలను ఈ ఆరు రూపాలు కవర్ చేస్తాయి:
!!మునుపటి పూర్తి లైన్ను మళ్లీ అమలు చేస్తుంది.sudo !!దాన్ని root గా మళ్లీ అమలు చేస్తుంది.!$మునుపటి లైన్లోని చివరి argument.!*మునుపటి లైన్లోని అన్ని arguments.!nhistory entry number n ను అమలు చేస్తుంది.!-nప్రస్తుతం ఉన్న స్థానంనుంచి వెనుకకు లెక్కిస్తుంది.!stringstringతో ప్రారంభమైన ఇటీవలి command ను అమలు చేస్తుంది.^old^newమునుపటి లైన్ను మళ్లీ అమలు చేస్తుంది. అందులోని మొదటిoldనుnewతో భర్తీ చేస్తుంది.
క్రింద ఉన్న ప్రతిదీ మీ స్వంత server లోని interactive prompt వద్ద టైప్ చేయాలి. Scripts లో history expansion నిలిపివేయబడి ఉంటుంది. చివరి section లో దీనిని వివరిస్తుంది.
ఒక పొడవైన path ను ఒక్కసారి టైప్ చేయడం
ఇది ఈ విధానం నిజంగా ఉపయోగపడే సందర్భం. మీరు release directory సిద్ధం చేస్తున్నారు. path చాలా పొడవుగా ఉంది. దాన్ని రెండోసారి టైప్ చేస్తే typo వచ్చే అవకాశం ఉంటుంది.
sudo mkdir -p /srv/www/app/releases/2026-08-07
sudo chown -R deploy:deploy !$
ls -ld !$
sudo -u deploy nano !$/config.envప్రతి line ను అమలు చేయడానికి ముందు, expansion ద్వారా bash రూపొందించిన line ను ముద్రిస్తుంది:
sudo chown -R deploy:deploy /srv/www/app/releases/2026-08-07ఆ echo మీ తనిఖీ. command output చూడకముందు దాన్ని చదవండి. ఎందుకంటే bash కి !$ అంటే ఏమిటో నిర్ణయించిన విధానాన్ని మీరు చూడగలిగే ఏకైక అవకాశం అదే.
bash మీరు టైప్ చేసిన !$ ను కాకుండా, expanded line ను history లో నిల్వ చేస్తుంది. అందువల్ల ఈ chain పనిచేస్తుంది. line 3 తన చివరి argument ను expanded line 2 నుంచి తీసుకుంటుంది. line 4 దాన్ని line 3 నుంచి తీసుకుంటుంది. designator తర్వాత text రావచ్చని కూడా line 4 చూపిస్తుంది. !$/config.env అనేది చివరలో /config.env ఉన్న path గా మారుతుంది. ఎందుకంటే word designator, / వద్ద ముగుస్తుంది.
అదే session నుంచి మరో ఉదాహరణ. file ను edit చేసిన తర్వాత, అది ఉన్న directory ను list చేయాలనుకుంటున్నారు:
ls -l !$:h:h head modifier. ఇది path నుంచి చివరి component ను తొలగిస్తుంది. dirname కూడా ఇదే పని చేస్తుంది. :t చివరి component ను మాత్రమే ఉంచుతుంది. :r extension ను తొలగిస్తుంది. :e extension ను మాత్రమే ఉంచుతుంది.
!! మరియు sudo !! తో చివరి command ను మళ్లీ అమలు చేయడం
మీరు sudo ను మర్చిపోతారు. Service manager కూడా అదే విషయాన్ని చెబుతుంది:
systemctl restart nginxFailed to restart nginx.service: Interactive authentication required.sudo !!Bash !! ను మునుపటి line లోని text తో భర్తీ చేస్తుంది. అందువల్ల shell sudo systemctl restart nginx ను అమలు చేస్తుంది.
!! అనేది మునుపటి line ఏదైతే ఉందో అదే. ఇక్కడే సాధారణ ప్రమాదం జరుగుతుంది. విఫలమైనది చివరి command అని మీరు అనుకుంటారు. కానీ ఆ తర్వాత మీరు cd లేదా history ను అమలు చేసి ఉండవచ్చు. లేదా విఫలమైన command రెండు lines ముందు ఉండవచ్చు. అప్పుడు sudo !! తప్పు command ను root హక్కులతో అమలు చేస్తుంది. మీకు ఖచ్చితంగా తెలియకపోతే ముందుగా దాన్ని print చేయండి:
sudo !!:p:p విస్తరించిన line ను print చేస్తుంది, కానీ దాన్ని అమలు చేయదు. Print అయిన line మీ history కి జోడించబడుతుంది. అది సరైనదిగా కనిపిస్తే, తదుపరి line లో plain !! ను అమలు చేసి దాన్ని నడపవచ్చు.
!$ తో చివరి ఆర్గ్యుమెంట్ను మళ్లీ ఉపయోగించడం
!$ అనేది మునుపటి లైన్లోని చివరి పదం. మీరు ఎక్కువగా ఉపయోగించేది ఇదే రూపం, ఎందుకంటే సాధారణంగా మీరు పని చేసేది చివరి పదంపైనే ఉంటుంది: ఒక path లేదా service name.
sudo systemctl status nginx
sudo systemctl reload !$ఇక్కడ రెండు విషయాలు చాలామందికి ఆశ్చర్యం కలిగిస్తాయి.
మొదటిది, !$ అనేది చివరి పదం, మీరు ఉద్దేశించిన చివరి ఆర్గ్యుమెంట్ కాదు. మునుపటి లైన్ redirection తో ముగిస్తే, చివరి పదం redirect target అవుతుంది:
sudo nginx -T > /tmp/nginx-dump.conf
less !$అది ఇక్కడ సరిగ్గా పనిచేస్తుంది. కానీ journalctl -u nginx > /tmp/log.txt తర్వాత, !$ అనేది /tmp/log.txt, nginx కాదు. echo చేసిన లైన్ను చదవండి.
రెండవది, ఈ expansion పాఠ్యరూపంలో జరుగుతుంది. అందువల్ల variable మళ్లీ expand కాకుండానే వస్తుంది. ls $HOME/backups తర్వాత, !$ మీకు $HOME/backups అక్షరాలను ఇస్తుంది. తరువాత bash దాన్ని సాధారణ parameter లాగా మళ్లీ expand చేస్తుంది. ఈ క్రమాన్ని గుర్తుంచుకోండి: history expansion, parameter expansion కు మరియు $( ) తో command substitution కు ముందే జరుగుతుంది. అందువల్ల అది values ను కాకుండా text ను మాత్రమే చూస్తుంది.
దగ్గరగా ఉండే ఇతర రూపాలు కూడా తెలుసుకోవాలి. !^ మొదటి argument, !:2 రెండవ argument, !:2-4 ఒక range. !!:$ అనేది !$ ను రాసే దీర్ఘ రూపం.
మీరు దాన్ని అమలు చేయడానికి ముందు text చూడాలనుకుంటే, Alt-. నొక్కండి. (లేదా Esc, తరువాత . నొక్కండి.) Readline మునుపటి command యొక్క చివరి argument ను నేరుగా మీ prompt లోకి చేర్చుతుంది. అక్కడ మీరు దాన్ని edit చేయవచ్చు. అంతకు ముందు ఉన్న command యొక్క చివరి argument కు వెళ్లడానికి దాన్ని మళ్లీ నొక్కండి. మీరు Enter నొక్కే వరకు ఏదీ అమలు కాదు.
!*
!* అనేది మునుపటి పంక్తిలోని మొదటి పదాన్ని మినహాయించిన మిగతా ప్రతి పదం.
stat /srv/www/app/shared/config.env /srv/www/app/shared/secrets.env
sudo chmod 600 !*"మొదటి పదాన్ని మినహాయించి" అనే భాగం ఇక్కడ ముఖ్యమైనది. !* పదం 0ను మాత్రమే తొలగిస్తుంది; మరేదీ తొలగించదు. అందువల్ల options కూడా paths తో పాటు పంపబడతాయి. ls -l file1 file2 తర్వాత, !* అనేది -l file1 file2. కాబట్టి sudo chmod 600 !* విఫలమవుతుంది, ఎందుకంటే chmod కు -l argument గా అందుతుంది. పదాలను సున్నా నుంచి లెక్కించి, బదులుగా ఒక slice తీసుకోండి: !!:2* అంటే word 2 నుంచి చివరి word వరకు.
ఇదే సమస్య sudo తో కూడా వస్తుంది. sudo chown deploy:deploy /srv/www/app తర్వాత, word 0 అనేది sudo మరియు word 1 అనేది chown. అందువల్ల !* తదుపరి command కు chown deploy:deploy /srv/www/app ను అందిస్తుంది. సాధారణంగా మీకు కావలసింది ఇది కాదు.
స్థానం ఆధారంగా !n మరియు !-n తో ఒక command ఎంచుకోండి
history ప్రతి entry ముందు సంఖ్యతో జాబితాను ప్రదర్శిస్తుంది.
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 entry 513 ను మళ్లీ అమలు చేస్తుంది. !-2 మీరు ప్రస్తుతం టైప్ చేస్తున్న line నుంచి లెక్కించినప్పుడు, రెండు lines ముందు ఉన్న entryని అమలు చేస్తుంది. అందువల్ల !-1 మరియు !! ఒకే విషయాన్ని సూచిస్తాయి.
వాటిని ఉపయోగించే ముందు వెంటనే సంఖ్యలను తనిఖీ చేయండి. మీరు ఆలోచించకుండా అమలు చేసిన ls సహా ఏదైనా command ను అమలు చేసిన ప్రతిసారీ !-2 కొత్త స్థానాన్ని సూచిస్తుంది. ఒకే session లో absolute numbers స్థిరంగా ఉంటాయి. కానీ అదే box లోని రెండవ session లో అవి అదే numbers కావు. తరువాతి login సమయంలో history file మళ్లీ చదివిన తర్వాత కూడా అవి అదే numbers కావు. నిన్న గుర్తుపెట్టుకున్న number ఈరోజు వేరే command ను సూచిస్తుంది.
!stringతో prefix ఆధారంగా కమాండ్ను మళ్లీ అమలు చేయడం
!string, string తో ప్రారంభమయ్యే ఇటీవలి కమాండ్ను అమలు చేస్తుంది.
!ssఇది పై జాబితాలోని ss -tulpn ను మళ్లీ అమలు చేస్తుంది. Linux serverలో ఏ ports openగా ఉన్నాయో అనే విభాగంలో వివరించిన listening socket తనిఖీ అదే. !?string? ప్రారంభంలో కాకుండా lineలో ఎక్కడైనా సరిపోలుతుంది. కమాండ్ పేరు గుర్తు లేకపోయినా argument గుర్తున్నప్పుడు ఇది ఉపయోగకరంగా ఉంటుంది.
Prefixను పొడవుగా ఉంచండి. !s, ఇటీవలి క్రమంలో చివరిగా అమలైన ss, sudo, systemctl లేదా shutdown లో ఏదో ఒకదానితో సరిపోలుతుంది. అమలు అయ్యే వరకు ఏది సరిపోలిందో మీకు తెలియదు. !string:p సరిపోలిన commandను అమలు చేయకుండా ప్రింట్ చేస్తుంది. ఏదీ సరిపోలకపోతే, bash bash: !ss: event not found ను ప్రింట్ చేసి ఏదీ అమలు చేయదు. ఇదే సురక్షితమైన ఫలితం.
^old^new తో ఒక టైపోను సరిచేయండి
sudo systemctl status ngnixUnit ngnix.service could not be found.^ngnix^nginxShell మునుపటి పంక్తిని మళ్లీ అమలు చేస్తుంది. అందులోని మొదటి ngnix ను nginx తో భర్తీ చేస్తుంది. మొదటి సరిపోలిక మాత్రమే మారుతుంది. ప్రతి సరిపోలికను మార్చడానికి దీర్ఘ రూపమైన !!:gs/ngnix/nginx/ ను ఉపయోగించండి. ఇందులో s అంటే substitute, g అంటే మొత్తం పంక్తిపై ఆ మార్పును చేయడం.
అమలు చేయడానికి ముందు expansion ను ముద్రించండి
మీ ఉద్దేశం కానిదాన్ని expansion అమలు చేసే ప్రమాదాన్ని రెండు అలవాట్లు నివారిస్తాయి.
మొదటిది :p. దీన్ని మీరు ఇప్పటికే చూశారు. Expansion కు దీన్ని జోడిస్తే, bash దాన్ని అమలు చేయకుండా ఫలితాన్ని ముద్రిస్తుంది: !!:p లేదా !systemctl:p. ముద్రించిన లైన్ మీ history లోకి వెళ్తుంది. కాబట్టి వెంటనే !! అమలు చేస్తే, మీరు ఇప్పుడే చూసినదే నడుస్తుంది.
రెండవది మరింత సురక్షితం. ఎందుకంటే మీరు ఏదీ గుర్తుంచుకోవాల్సిన అవసరం లేకుండా ప్రతి expansion కు ఇది వర్తిస్తుంది:
shopt -s histverifyఆ లైన్ను ~/.bashrc లో ఉంచండి. histverify సెట్ అయి ఉంటే, మీరు Enter నొక్కగానే expansion అమలు కాదు. Bash expanded line ను మీ prompt లో తిరిగి ఉంచుతుంది. మీరు దాన్ని చదివి సవరించవచ్చు. అమలు చేయడానికి రెండోసారి Enter నొక్కాలి. దీనికి ఒక keystroke మాత్రమే అదనంగా అవసరం. ఈ విధంగా మొత్తం ప్రమాద వర్గమే తొలగిపోతుంది. దీనికి readline అవసరం. అందువల్ల ఇది interactive prompt వద్ద మాత్రమే పనిచేస్తుంది.
పని చేయడానికి మరొక మార్గం Ctrl-R. ఇది ఎప్పుడూ ఏదీ expand చేయదు. Ctrl-R నొక్కి, command లోని కొంత భాగాన్ని type చేయండి. Prompt reverse-i-search prompt గా మారుతుంది. మీరు type చేస్తున్నప్పుడు అత్యంత తాజా match కనిపిస్తుంది. పాత matches కు వెళ్లడానికి మళ్లీ Ctrl-R నొక్కండి. కనిపిస్తున్న line ను అమలు చేయడానికి Enter నొక్కండి. Search ను రద్దు చేసి, అసలు prompt ను తిరిగి పొందడానికి Ctrl-G నొక్కండి. Left arrow key search ను ముగిస్తుంది. Matched line మీ prompt లోనే ఉంటుంది, కాబట్టి దాన్ని సవరించవచ్చు.
ముందుగా command ను చూడాలనుకుంటే Ctrl-R ఉపయోగించండి. Command ఒక line ముందే ఉండి, అది ఇంకా screen పై కనిపిస్తుంటే !! మరియు !$ ఉపయోగించండి.
echo "done!" లో event not found అని ఎందుకు చూపిస్తుంది
echo "deploy done!"bash: !": event not foundQuoting పరిష్కరించబడకముందే history expansion అమలవుతుంది. Double quotes కూడా ! character ను రక్షించవు. Single quotes మరియు backslash మాత్రమే రక్షిస్తాయి. అందువల్ల echo 'deploy done!' మీరు ఆశించిన విధంగా output ఇస్తుంది. Backslash కూడా expansion ను ఆపుతుంది. అయితే double quotes లో ఉన్నప్పుడు bash ఆ backslash ను output లో ఉంచుతుంది. కాబట్టి single quotes ఉపయోగించడం సరైన పరిష్కారం.
ఈ సమస్య passwords తో ఎక్కువగా ఎదురవుతుంది. ఎందుకంటే బలమైన password లో సాధారణంగా ! ఉంటుంది. mysql -u app -p"S3cret!pass" వంటి command event-not-found error తో విఫలమవుతుంది. లేదా ఏదైనా history entry సరిపోతే, వేరే string ను నిశ్శబ్దంగా పంపవచ్చు. Single quotes ఉపయోగించండి. ఇంకా మంచిది, tool మిమ్మల్ని prompt చేయనివ్వండి. అప్పుడు secret command line కు చేరదు. మీ account hygiene లో ఈ అలవాటు కూడా భాగమే: కొత్త VPS పై ప్రారంభించే మొదటి పది నిమిషాల్లో keys మరియు passwords ను ఎలా నిర్వహించాలో కొత్త VPS పై మొదటి పది నిమిషాలు చూడండి.
! characters ఎక్కువగా ఉన్న text block ను paste చేయబోతే, ఆ session కోసం set +H తో expansion ను ఆపండి. తిరిగి set -H తో ప్రారంభించండి.
HISTSIZE, HISTFILESIZE మరియు మీ history నిల్వ ఉండే స్థలం
రెండు variables ఉన్నాయి. పేర్లు దగ్గరగా ఉండటంతో వీటిని తరచుగా కలిపేస్తారు.
HISTSIZEఅంటే ప్రస్తుతం నడుస్తున్న shell memoryలో ఎన్ని commands ఉంచుతుందో.HISTFILESIZEఅంటే diskలోని fileలో ఎన్ని lines ఉంచుతుందో,~/.bash_historyHISTFILEవేరే విధంగా పేర్కొంటే తప్ప.
shell exit అయినప్పుడు fileలో రాస్తుంది. ఆ సమయంలో అది HISTFILESIZE linesకు కుదించబడుతుంది. Ubuntu యొక్క default ~/.bashrc విలువలు 1000 మరియు 2000గా ఉంచుతుంది. మీ configurationలో వాస్తవంగా ఏ విలువలు ఉన్నాయో చూడండి:
grep HIST ~/.bashrc
echo "$HISTSIZE $HISTFILESIZE $HISTFILE"మీకు తెలుసు తాను అమలు చేసిన commands కోసం చేసే !string searches తరచుగా ఫలితం ఇవ్వకపోతే, రెండు విలువలను పెంచండి. 10000 మరియు 20000 సాధారణ విలువలు. File plain text కావడంతో దీనికి దాదాపు ఎటువంటి ఖర్చు ఉండదు. Negative value అంటే ఎటువంటి పరిమితి లేదని అర్థం.
మీరు ఒక వారం తర్వాత server వద్దకు తిరిగి వచ్చినప్పుడు timestamps ఉపయోగకరంగా ఉంటాయి:
export HISTTIMEFORMAT='%F %T 'అప్పుడు history ప్రతి entry ముందు date మరియు timeను ముద్రిస్తుంది. ఎందుకంటే ప్రతి commandకు ముందు epoch seconds ఉన్న comment lineను bash fileలో రాయడం ప్రారంభిస్తుంది.
ఒకటి కంటే ఎక్కువ terminals ఉపయోగించినప్పుడు history కనిపించకపోవడం సాధారణ ఫిర్యాదు. ప్రతి shell తన listను memoryలో ఉంచి, exit సమయంలో దాన్ని fileలో రాస్తుంది. అందువల్ల histappend లేకపోతే, చివరగా close అయిన shell మిగతా shells save చేసిన సమాచారాన్ని overwrite చేస్తుంది. రెండు settings దీనిని పరిష్కరిస్తాయి:
shopt -s histappend
export PROMPT_COMMAND='history -a'histappend shell తన listను fileను replace చేయకుండా, దాని చివర add చేయేలా చేస్తుంది. history -a ప్రతి prompt తర్వాత కొత్త linesను append చేస్తుంది. అందువల్ల sessionను సక్రమంగా close చేయకుండా kill చేసినా, దాని commands fileలో మిగులుతాయి. Ubuntu యొక్క default ~/.bashrc ఇప్పటికే histappendను సెట్ చేస్తుంది. మీరు నిర్వహించే machines సంఖ్య పెరిగే కొద్దీ ఇది మరింత ముఖ్యమవుతుంది. ఎందుకంటే history ప్రతి userకు, ప్రతి machineలో విడిగా నిల్వ ఉంటుంది. కాబట్టి మీరు ఒక workstation నుంచి అనేక serversను నిర్వహిస్తున్నప్పుడు, మీకు కావాల్సిన !$ మరొక hostలో ఉండవచ్చు.
Bash historyలో secrets ఉండకుండా చూడటం
HISTCONTROL ఏ పంక్తులు అసలు సేవ్ చేయాలో నిర్ణయిస్తుంది.
ignorespacespace తో ప్రారంభమయ్యే ప్రతి పంక్తిని తొలగిస్తుంది.ignoredupsమునుపటి పంక్తితో పూర్తిగా సమానమైన పంక్తిని తొలగిస్తుంది.ignorebothపై రెండు చర్యలను చేస్తుంది.erasedupsసేవ్ చేస్తున్న పంక్తి యొక్క పాత ప్రతులన్నింటినీ తొలగిస్తుంది.
export HISTCONTROL=ignorebothignorespace సక్రియంగా ఉన్నప్పుడు, ప్రారంభంలో ఒక space ఉంచిన command memoryలోని listలోకి చేరదు. అందువల్ల అది fileలోకి కూడా చేరదు. దానిపై ఆధారపడే ముందు echo "$HISTCONTROL" తో విలువను పరిశీలించండి. Ubuntu యొక్క default user .bashrc, ignoreboth ను సెట్ చేస్తుంది. అయితే root shell లేదా minimal image లో అది unset అయి ఉండవచ్చు. అప్పుడు ప్రారంభంలోని space ఎలాంటి ప్రభావం చూపదు, మరియు ఆ పంక్తి ఇతర పంక్తుల్లాగే నిల్వ అవుతుంది.
ఇది ఏది రక్షిస్తుందో వాస్తవికంగా అంచనా వేయండి. ఆ పంక్తి ~/.bash_history లో ఉండదు. Process నడుస్తున్నంతకాలం అది ps outputలో కనిపిస్తుంది. అందువల్ల అదే machineలోని ఇతర userలు దాన్ని అక్కడ చదవగలరు. sudo అమలు చేసిన commandను system logలో నమోదు చేస్తుంది. History file plain textలో ఉంటుంది. కాబట్టి దానికి mode 600 ఉంచండి. మీ home directoryను చదవగల ఎవరైనా మీ చివరి కొన్ని వేల commandsను కూడా చదవగలరని గుర్తుంచుకోండి.
ఏదైనా సున్నితమైన సమాచారం ఇప్పటికే listలో ఉంటే, ఆ entryని తొలగించి fileను మళ్లీ రాయండి:
history
history -d 517
history -whistory -d ఆ entryని memory నుంచి తొలగిస్తుంది. history -w ప్రస్తుత listను fileపై రాస్తుంది. history -c మొత్తం listను ఖాళీ చేస్తుంది. Secretsకు బదులుగా అనవసరమైన outputను నియంత్రించడానికి సంబంధించిన knob HISTIGNORE. Search ఫలితాల్లో ఉపయోగకరమైన matches మాత్రమే కనిపించేలా, ఆ linesను list నుంచి HISTIGNORE='ls:pwd:history:clear' ఉంచుతుంది.
షెల్ స్క్రిప్ట్లో history expansion ఎందుకు పనిచేయదు
History expansion interactive shells కు సంబంధించినది. Script non-interactive shell లో నడుస్తుంది. అక్కడ history list enabled అయి ఉండదు మరియు expansion off లో ఉంటుంది. అందువల్ల !! మరియు !$ ఆ line లో సాధారణ text గానే ఉంటాయి. Script లోని sudo !!, !! అనే పేరుగల command ను అచ్చంగా అమలు చేయమని sudo కు చెబుతుంది. అది విఫలమవుతుంది.
మీరు ప్రస్తుతం ఉపయోగిస్తున్న ఏదైనా shell ను పరిశీలించండి:
echo $-Output ప్రస్తుత option flags సమాహారంగా ఉంటుంది. ఉదాహరణకు అది himBHs లాగా ఉండవచ్చు. i అంటే shell interactive గా ఉందని, H అంటే history expansion enabled గా ఉందని అర్థం. అదే line ను script లో నడిపితే ఈ రెండు letters లో ఏదీ కనిపించదు.
ఇదే మీ shell పనిలోని రెండు భాగాల మధ్య తేడా. Prompt వద్ద కనిపిస్తున్న commands లో keystrokes తగ్గించడానికి !$ మరియు Ctrl-R ఉపయోగపడతాయి. File లో మాత్రం విషయాలకు పేర్లు ఇవ్వాలి. Path ను variable లో ఉంచండి లేదా command substitution తో output ను capture చేయండి. మీ వ్యక్తిగత history పై ఆధారపడే script ను మరొకరు నడిపితే వేరే ఫలితం వస్తుంది. అది script ఉద్దేశానికి పూర్తిగా విరుద్ధం.
అందుకే ఈ page లోని ప్రతి example ను live prompt వద్ద type చేయడానికి ఉద్దేశించారు. వాటిని .sh file లోకి paste చేస్తే అదే విధంగా పనిచేయవు.
FAQ
bashలో !! ఏమి చేస్తుంది?
!! మునుపటి command line యొక్క పూర్తి పాఠ్యాన్ని విస్తరిస్తుంది. అందువల్ల sudo !! మీ చివరి command ను root గా మళ్లీ అమలు చేస్తుంది. ఈ విస్తరణ పాఠ్యస్థాయిలో జరుగుతుంది మరియు bash ఆ line ను parse చేయడానికి ముందు పూర్తవుతుంది. అమలు చేయడానికి క్షణం ముందు bash పూర్తయిన line ను చూపిస్తుంది. మునుపటి line ఏమిటో మీకు ఖచ్చితంగా తెలియకపోతే ముందుగా sudo !!:p టైప్ చేయండి. :p విస్తరించిన పాఠ్యాన్ని అమలు చేయకుండా చూపిస్తుంది. అది చూపించిన line ను historyలో కూడా చేర్చుతుంది. అందువల్ల తరువాత !! దాన్ని అమలు చేస్తుంది.
మునుపటి command యొక్క చివరి argument ను ఎలా మళ్లీ ఉపయోగించాలి?
!$ ను ఉపయోగించండి. sudo mkdir -p /srv/www/app/releases తర్వాత, ls -ld !$ line ls -ld /srv/www/app/releases గా మారుతుంది. ఇది lineలోని చివరి పదాన్ని తీసుకుంటుంది. కాబట్టి చివరలో ఉన్న redirection target చివరి పదంగా పరిగణించబడుతుంది. దానికి text ను జోడించవచ్చు: !$/config.env path కు text ను జోడిస్తుంది, ఎందుకంటే word designator / వద్ద ఆగుతుంది. interactive ప్రత్యామ్నాయం Alt-.. ఇది అదే text ను మీ promptలో చేర్చుతుంది. కాబట్టి Enter నొక్కే ముందు దాన్ని చదవవచ్చు.
నా textలో exclamation mark ఉన్నప్పుడు bash "event not found" అని ఎందుకు చెబుతుంది?
Double quotes ! ను history expansion నుంచి రక్షించవు. అందువల్ల echo "done!" bash ను history event కోసం వెతికేలా చేస్తుంది, మరియు అది bash: !": event not found ను చూపిస్తుంది. Single quotes మాత్రం దాన్ని రక్షిస్తాయి. కాబట్టి echo 'done!' గా రాయండి. Backslash కూడా expansion ను ఆపుతుంది. అయితే double quotes లోపల bash ఆ backslash ను outputలో ఉంచుతుంది. ! కలిగిన పొడవైన block ను paste చేయాలంటే, ఆ session కోసం set +H తో expansion ను ఆపండి.
నా shell scriptలో !! మరియు !$ ఎందుకు పనిచేయవు?
History expansion interactive shellsలో మాత్రమే ప్రారంభించబడుతుంది. Script non-interactively నడుస్తుంది. అందువల్ల shell history list ను రూపొందించదు, మరియు !! lineలో సాధారణ textగా మిగిలిపోతుంది. మీరు ఏ రకమైన shellలో ఉన్నారో చూడటానికి echo $- అమలు చేయండి. Interactive shell i మరియు H సహా flags ను చూపిస్తుంది. Script అయితే రెండింటినీ చూపించదు. Scriptsలో variable లేదా command substitution ను ఉపయోగించండి.
Password ను నా bash historyలోకి వెళ్లకుండా ఎలా ఉంచాలి?
~/.bashrc లో HISTCONTROL=ignorespace లేదా HISTCONTROL=ignoreboth ను సెట్ చేసి, command ను ఒక single spaceతో ప్రారంభించండి. అప్పుడు అది ఎప్పటికీ సేవ్ చేయబడదు. ముందుగా echo "$HISTCONTROL" తో విలువను నిర్ధారించండి. అది unset అయి ఉంటే, ప్రారంభంలోని space వల్ల ప్రయోజనం ఉండదు. ఇది line ను ~/.bash_history నుంచి మాత్రమే తొలగిస్తుంది. Command నడుస్తున్నప్పుడు అది ps లో ఇంకా కనిపిస్తుంది. అలాగే sudo అది అమలు చేసినదాన్ని log చేస్తుంది. Secret ఇప్పటికే సేవ్ అయి ఉంటే, history తో దాని number ను కనుగొనండి. తరువాత history -d <number> ను అమలు చేసి, దాని తరువాత history -w ను అమలు చేయండి. ఇది fileను తిరిగి రాస్తుంది.