SSD Nodes Learn 🎉 VPS $5.50/నెల నుండి
మార్గదర్శకాలు Matt Connorద్వారా Matt Connor · అప్‌డేట్ చేయబడింది 2026-08-16

Bash Globbing: Wildcards, nullglob, globstar మరియు extglob

Bash globbing ఆదేశం నడవకముందే filenames ను ఎలా విస్తరిస్తుందో తెలుసుకోండి. nullglob, dotglob, globstar మరియు extglob negation తో ఖచ్చితమైన ఉదాహరణలు చూడండి.

మీ ఆదేశం అమలుకాకముందు Bash globbing చేసే పని

Bash globbing అంటే ఆదేశం ప్రారంభమయ్యే ముందు `*.log వంటి pattern ను నిజంగా ఉన్న filenames యొక్క క్రమబద్ధీకరించిన జాబితాగా shell మార్చడం. rm *.log ఎప్పుడూ rm కు pattern ను పంపదు. Bash directory ను చదివి, pattern కు సరిపోలే పేర్లను ఉంచి, వాటిని sort చేసి, తరువాత ప్రతి పేరును ప్రత్యేక argument గా rm ను అమలు చేస్తుంది. Pattern ఉపయోగించబడిందని rm` program గుర్తించలదు.

Globbing గురించి ఆశ్చర్యంగా అనిపించే దాదాపు ప్రతి విషయం ఈ ఒక్క వాస్తవం నుంచే వస్తుంది. Matching ను shell, ఆ క్షణంలో ఉన్న files కు వ్యతిరేకంగా చేస్తుంది. Command కు పూర్తయిన జాబితా మాత్రమే కనిపిస్తుంది. దీనికి అధికారిక పేరు pathname expansion. రోజువారీ వాడుకలో దీనిని globbing అంటారు. రెండు పదాల అర్థం ఒకటే.

పాటించడానికి చిన్న directory tree ను రూపొందించండి

కింది ప్రతి ఉదాహరణ ఒకే files పై పనిచేస్తుంది. వాటిని temporary directory లో సృష్టించండి. అప్పుడు మీకు అవసరమైన files సమీపంలో ఉండవు, cleanup ను ఒక command తో చేయవచ్చు.

lab=$(mktemp -d)
cd "$lab"
mkdir -p logs archive/2025 archive/2026
touch app.log app.log.1 app.log.2 app.log.10 error.log debug.LOG
touch notes.txt notes.md README 'weekly report.log'
touch .env .apprc
touch logs/nginx.log logs/nginx.log.1
touch archive/2025/dec.log archive/2026/jan.log

mktemp -d కొత్త directory ను సృష్టించి దాని path ను తిరిగి ఇస్తుంది. $(...) ఆ path ను lab variable లో నిల్వ చేస్తుంది. ఈ syntax మీకు కొత్తగా ఉంటే, command output ను command substitution ఎలా capture చేస్తుందో అనే వివరణను పూర్తిగా చూడండి.

మీరు రూపొందించినదాన్ని పరిశీలించండి. అలాగే మీ shell ను తనిఖీ చేయండి, ఎందుకంటే చివర్లోని ఒక గమనిక version పై ఆధారపడి ఉంటుంది:

ls -a
bash --version

ఇక్కడ ఉన్నవన్నీ bash 4.0 మరియు తర్వాతి versions లో పనిచేస్తాయి. చివర్లోని globskipdots గమనిక bash 5.2 మరియు తర్వాతి versions కు వర్తిస్తుంది. August 2026 నాటికి ప్రస్తుత Ubuntu మరియు Debian releases వీటినే అందిస్తున్నాయి.

మొత్తం పాఠంలో ఉపయోగించే preview command printf '%s\n' PATTERN. ఇది ప్రతి match ను ఒక్కో line లో ముద్రిస్తుంది. Disk లో ఏ మార్పూ చేయదు. అందువల్ల మీకు నిర్ధారణ లేని ఏ pattern పై అయినా దీన్ని సురక్షితంగా అమలు చేయవచ్చు.

మూడు wildcards: star, question mark మరియు brackets

  • * ఖాళీగా ఉన్నదానితో సహా, characters యొక్క ఏదైనా వరుసకు సరిపోతుంది.
  • ? సరిగ్గా ఒక character కు సరిపోతుంది.
  • [...] brackets లోపల ఉన్న set నుంచి తీసుకున్న సరిగ్గా ఒక character కు సరిపోతుంది.
printf '%s\n' *.log
printf '%s\n' app.log.?
printf '%s\n' app.log.[0-9]
printf '%s\n' notes.*
printf '%s\n' *

మీరు రూపొందించిన file list తో రెండో line ను పోల్చండి. ? ఒక character కు మాత్రమే సరిపోతుంది; అంతకంటే ఎక్కువకు కాదు. అందువల్ల రెండు digits ఉన్న suffix ఆ pattern కు సరిపోదు. దాన్ని app.log.[0-9]* గా విస్తరించి, తేడాను చూడటానికి మళ్లీ run చేయండి.

ఈ మూడు wildcards కు రెండు నియమాలు వర్తిస్తాయి. ఏ wildcard కూడా ఎప్పుడూ / కు సరిపోదు. అందువల్ల pattern ఒకే directory level లోనే ఉంటుంది. అలాగే ప్రారంభంలో ఉన్న . ను అక్షరాలా type చేయాలి. కాబట్టి * తో ప్రారంభమయ్యే pattern ప్రతి hidden name ను దాటవేస్తుంది. అందుకే rm * మీ dotfiles ను మార్చకుండా ఉంచుతుంది.

Glob ఫలితాలు ప్రస్తుత locale యొక్క collation order ప్రకారం sorted గా వస్తాయి. ఇది character by character text sort. అందువల్ల 10 suffix, 2 suffix కంటే ముందు sorted అవుతుంది. పోలికలో వాటిలో దేనినీ number గా పరిగణించదు. printf '%s\n' app.log.* ను run చేసి, తరువాత ls -v app.log.* ను run చేసి రెండింటినీ పోల్చండి: ls -v embedded numbers ను వాటి value ప్రకారం sort చేస్తుంది. Pipeline లో అదే పని sort -V చేస్తుంది.

అక్షర తరగతులు మరియు పరిధులు

బ్రాకెట్లలో జాబితా, పరిధి లేదా నిరాకరణను రాయవచ్చు.

  • [ch] ఒక అక్షరాన్ని సరిపోలుస్తుంది; అది c లేదా h కావచ్చు.
  • [a-f] a నుంచి f వరకు ఉన్న పరిధిలోని ఒక అక్షరాన్ని సరిపోలుస్తుంది.
  • [!0-9] అంకె కాని ఒక అక్షరాన్ని సరిపోలుస్తుంది. [^0-9] కూడా ఇదే అర్థాన్ని ఇస్తుంది.
printf '%s\n' [dn]*
printf '%s\n' *.[A-Z]*
printf '%s\n' [A-Z]*

పరిధుల విషయంలో వేర్వేరు యంత్రాల మధ్య ఫలితాలు మారవచ్చు. పరిధి plain ASCII క్రమాన్ని కాకుండా ప్రస్తుత locale యొక్క collation order ఆధారంగా పరిష్కరించబడుతుంది. అందువల్ల కొన్ని సిస్టమ్‌లలో [a-z] పెద్ద అక్షరాలను కూడా సరిపోల్చవచ్చు. plain ASCII క్రమాన్ని బలవంతంగా ఉపయోగించే globasciiranges option Bashలో ఉంది. ఇటీవలి buildsలో ఇది defaultగా enable అయి ఉండవచ్చు. కాబట్టి ఊహించకుండా shopt globasciiranges ద్వారా మీ సిస్టమ్‌లోని అమరికను తనిఖీ చేయండి. ప్రతిచోటా ఒకే విధంగా సరిపోల్చాల్సిన script అయితే, పైభాగానికి సమీపంలో ప్రత్యేక lineలో LC_ALL=C ను set చేసి క్రమాన్ని స్వయంగా స్థిరపరచవచ్చు. అప్పుడు ప్రతి పరిధి తిరిగి plain byte orderను ఉపయోగిస్తుంది.

ఆ assignment స్వతంత్ర commandగా ఉండాలి. Prefixగా రాస్తే, LC_ALL=C ls [a-z]* కేవలం ls కోసం localeను set చేస్తుంది; మరేదానికీ కాదు. అంతేకాకుండా ls ప్రారంభమయ్యేలోపే shell తన స్వంత localeలో patternను expand చేసి ఉంటుంది. మొదటి sectionలో చెప్పిన నియమం ఇక్కడ మళ్లీ వర్తిస్తుంది.

Brace expansion globbing కాదు

Braces wildcard లాగా కనిపిస్తాయి, కానీ wildcard లాగా పనిచేయవు. Brace expansion, globbing కంటే చాలా ముందే జరుగుతుంది. ఇది disk ను ఎప్పుడూ పరిశీలించదు.

echo file{1,2,3}.txt
echo {01..10}
echo {a..e}
echo {0..20..5}

ఆ files ఏవీ లేవు. అయినప్పటికీ expansion జరుగుతుంది. ఇదే ప్రధాన తేడా: glob filesystem ను ప్రశ్నిస్తుంది, కానీ brace కేవలం text ను generate చేస్తుంది. అందుకే files ను కనుగొనడం కంటే సృష్టించడానికి braces సరైన సాధనం.

mkdir -p site/{css,js,img}
cp app.log{,.bak}
touch report-{2025,2026}-{01,02}.csv

cp app.log{,.bak} రెండు words గా విస్తరిస్తుంది: app.log మరియు app.log.bak. ఎందుకంటే comma కు ముందు ఉన్న ఖాళీ item అసలు text ను మళ్లీ ఉత్పత్తి చేస్తుంది. {01..10} తన zero padding ను కొనసాగిస్తుంది. ఎందుకంటే ఏదైనా endpoint కు ముందు zero ఉంటే, bash రూపొందించే ప్రతి number ను ఒకే width కు pad చేస్తుంది.

Expansion order వల్ల తరచుగా ఎదురయ్యే ఒక సమస్య కూడా అర్థమవుతుంది. Bash ముందుగా braces ను expand చేస్తుంది, తరువాత variables ను expand చేస్తుంది, చివరగా pathname expansion చేస్తుంది.

n=5
echo {1..$n}

$n number గా మారే సమయానికి Brace expansion ఇప్పటికే పూర్తయి ఉంటుంది. అందువల్ల ఏ range కూడా నిర్మించబడదు. seq 1 "$n" ను ఉపయోగించండి. లేదా for ((i=1; i<=n; i++)) గా రాసిన C-style loop ను ఉపయోగించండి.

ఏ pattern ఏదీ సరిపోలనప్పుడు ఏమి జరుగుతుంది

ఇది మొదటి విఫల పరిస్థితి. ప్రతి ఒక్కరూ కనీసం ఒకసారి దీనిలో చిక్కుకుంటారు. డిఫాల్ట్‌గా bash సరిపోలని pattern ను పూర్తిగా అలాగే ఉంచుతుంది. మీరు టైప్ చేసిన విధంగానే ఆ పదం command కు చేరుతుంది. అందువల్ల command *, ., t, m మరియు p అక్షరాలను స్వీకరించి, వాటిని filename లుగా పరిగణించడానికి ప్రయత్నిస్తుంది.

printf '%s\n' *.tmp

printf తో ఇది హానికరం కాదు. అయితే వస్తువులను సృష్టించే command తో ఇది హానికరం. .tmp files లేని directory లో touch *.tmp ను నడిపితే, దాని పేరు అక్షరాలా *.tmp గా ఉన్న file సృష్టించబడుతుంది. దాన్ని తరువాత తొలగించేటప్పుడు shell దాన్ని మళ్లీ expand చేయకుండా quoting ఉపయోగించాలి: rm -- '*.tmp'.

రెండు shell options ఈ నియమాన్ని మార్చుతాయి. ఏదీ సరిపోలని pattern పై ఒక్కో option ను పరీక్షించి, తరువాత దాన్ని unset చేయండి.

shopt -s nullglob
printf '%s\n' *.tmp
shopt -u nullglob

shopt -s failglob
printf '%s\n' *.tmp
shopt -u failglob

nullglob సరిపోలని pattern ను పూర్తిగా ఏమీ లేకుండా expand చేస్తుంది. అందువల్ల మీరు రాసిన దానికంటే తక్కువ arguments తో command నడుస్తుంది. Loop లో ఇది అవసరమైన ప్రవర్తన. nullglob off లో ఉన్నప్పుడు, for f in *.tmp తన body ని ఒకసారి నడుపుతుంది. ఆ సమయంలో f లో literal pattern ఉంటుంది. ఇలా చేసే దాదాపు ప్రతి script లో ఇది bug అవుతుంది. nullglob on లో ఉన్నప్పుడు body zero సార్లు నడుస్తుంది.

nullglob కు ప్రత్యేకమైన ప్రమాదం ఉంది. దాని అన్ని arguments తొలగించబడినా command నడుస్తూనే ఉంటుంది. ls *.nope అనేది ఖాళీ ls గా మారుతుంది. ఇది మొత్తం directory ని list చేస్తుంది. grep -l needle *.nope అనేది grep -l needle గా మారుతుంది. చదవడానికి దానికి file ఏదీ ఉండదు. అందువల్ల అది standard input కోసం వేచి ఉండి, frozen అయినట్లు కనిపిస్తుంది. అవసరమైన loop చుట్టూ nullglob ను on చేయండి. Loop తర్వాత మళ్లీ off చేయండి.

failglob మరో విధానాన్ని అనుసరిస్తుంది. సరిపోలని pattern ను error గా పరిగణిస్తుంది. bash దాన్ని report చేస్తుంది. Command అసలు నడవదు. Interactive shell కు ఇది మంచి setting. తప్పుగా టైప్ చేసిన pattern ను literal name గా rm కు పంపకుండా ఇది ఆపుతుంది.

దాచిన ఫైళ్లు: dotglob

shopt -s dotglob
printf '%s\n' *
shopt -u dotglob

ఆ block ను అమలు చేసి, ముందున్న సాధారణ printf '%s\n' * తో వచ్చిన listing ను పోల్చండి. dotglob ప్రారంభంలోని dot నియమాన్ని తొలగిస్తుంది. అందువల్ల * దాచిన పేర్లకు కూడా సరిపోతుంది. . మరియు .. entries మాత్రం dotglob ఉన్నప్పటికీ ఎల్లప్పుడూ మినహాయించబడతాయి.

dotglob లేకుండా దాచిన ఫైళ్లను చేరుకోవడానికి సాధారణంగా .* ఉపయోగించేవారు. అయితే ఇది గతంలో ప్రమాదకరంగా ఉండేది. 5.2 కంటే ముందు Bash సంస్కరణల్లో .*, . మరియు .. కు కూడా సరిపోవడంతో, chmod -R 755 .* వంటి recursive command నేరుగా parent directory లోకి వెళ్లేది. Bash 5.2 లో చేర్చిన globskipdots option దీనిని మార్చింది. ఇది default గా enable అయి ఉంటుంది. అందువల్ల ప్రతి expansion నుంచి . మరియు .. మినహాయించబడతాయి. దానిపై ఆధారపడే ముందు shopt globskipdots ను అమలు చేయండి. పాత box లో ఈ option ఉండకపోవచ్చు.

globstar: ట్రీలో అన్ని స్థాయిల్లో matching

shopt -s globstar
printf '%s\n' **/*.log
printf '%s\n' **/
shopt -u globstar

globstar సెట్ అయి ఉంటే, పూర్తి path component గా ఉండే **, సున్నా స్థాయితో సహా ఏ లోతులోనైనా ఉన్న files మరియు directories కు match అవుతుంది. అందువల్ల **/*.log ప్రస్తుత directory తో పాటు logs/ మరియు archive/ కింద ఉన్న ప్రతిదానినీ కూడా కవర్ చేస్తుంది. చివరలో slash ఉన్న **/ directories కు మాత్రమే match అవుతుంది. దీంతో ట్రీ నిర్మాణాన్ని త్వరగా చూడవచ్చు.

globstar సెట్ చేయకపోతే, ** సాధారణ * లా పనిచేసి ఒకే directory లో పరిమితం అవుతుంది. option ఆఫ్‌లో ఉంచి అదే pattern ను అమలు చేసి ఫలితాలను పోల్చండి. వేరే చోటు నుంచి కాపీ చేసిన recursive pattern మీరు ఆశించిన దానికంటే చాలా తక్కువ ఫలితాలను ఇస్తే, సాధారణంగా కారణం ఇదే. ప్రతి bash లో globstar డిఫాల్ట్‌గా ఆఫ్‌లో ఉంటుంది.

తెలుసుకోవాల్సిన ఒక పరిమితి ఉంది: ** directories కు ఉన్న symbolic links ను అనుసరించదు. symbolic links తో కలిపిన ట్రీ కోసం find -L అవసరం.

nocaseglob, పెద్దచిన్న అక్షర భేదాన్ని పట్టించుకోని పేర్ల కోసం

shopt -s nocaseglob
printf '%s\n' *.log
shopt -u nocaseglob

nocaseglob ఫైల్ పేర్ల సరిపోలింపులో పెద్దచిన్న అక్షర భేదాన్ని విస్మరిస్తుంది. అందువల్ల పెద్ద అక్షరాలతో ఉన్న .LOG suffix, చిన్న అక్షరాలతో ఉన్న .log pattern కు సరిపోతుంది. ఈ listing ను మొదటి section లో ఉన్న listing తో పోల్చండి. ఈ option ను వెంటనే మళ్లీ off చేయండి. ఇది on లో ఉంటే, ఆ shell లో తరువాత అమలు చేసే ప్రతి command కు matching విధానం మారుతుంది. ఒక గంట తర్వాత దీన్ని debug చేయడం గందరగోళంగా ఉంటుంది.

nocaseglob ఫైల్ పేరు expansion కు మాత్రమే వర్తిస్తుంది. case statement లో లేదా double bracket test లో pattern matching కోసం ఉపయోగించే సంబంధిత option nocasematch. ఈ రెండు options ను విడిగా set చేయాలి.

extglob: “ఇది కాకుండా” అని చెప్పగల patterns

Extended patterns డిఫాల్ట్‌గా ఆఫ్‌లో ఉంటాయి. వాటిని ప్రత్యేక లైన్‌లో ఆన్ చేయండి:

shopt -s extglob

ఇవికి ఐదు రూపాలు ఉన్నాయి. ప్రతి రూపం | తో వేరు చేసిన patterns జాబితాను స్వీకరిస్తుంది:

  • ?(list) సున్నా లేదా ఒక occurrence కు సరిపోతుంది.
  • *(list) సున్నా లేదా అంతకంటే ఎక్కువ occurrences కు సరిపోతుంది.
  • +(list) ఒకటి లేదా అంతకంటే ఎక్కువ occurrences కు సరిపోతుంది.
  • @(list) ప్రత్యామ్నాయాల్లో ఖచ్చితంగా ఒకదానికి సరిపోతుంది.
  • !(list) ఏ ప్రత్యామ్నాయానికీ సరిపోని దేనికైనా సరిపోతుంది.

Extended pattern ను option ఇప్పటికే ఆన్‌లో ఉన్న shell చదవాలి. అందువల్ల దిగువ batch, bash -O extglob తో ప్రారంభించే చిన్న script లో ఉండాలి. కొత్త shell ఫైల్‌లోని ఒక్క లైన్‌ను చదవకముందే shopt option ను సెట్ చేయడానికి -O flag ఉపయోగపడుతుంది. అందువల్ల అందులోని ప్రతి pattern సరిగ్గా parse అవుతుంది. క్రమం ఎందుకు ముఖ్యమో ఈ section లోని చివరి paragraph వివరిస్తుంది.

cat > patterns.sh <<'EOF'
printf '%s\n' @(app|error).log
printf '%s\n' app.log.+([0-9])
printf '%s\n' *.@(md|txt)
printf '%s\n' !(*.log)
printf '%s\n' !(*.log|*.md|README)
EOF
bash -O extglob patterns.sh

+([0-9]) అంటే ఒకటి లేదా అంతకంటే ఎక్కువ digits. అందువల్ల ఇది ఏ పొడవున్న numbered suffix కైనా సరిపోతుంది. ఇదే ఇంతకుముందు ఉన్న ? పరిమితికి పరిష్కారం. రెండు patterns ను వరుసగా అమలు చేసి ఫలితాన్ని చూడటం ఉపయోగకరం.

“దీనిని మినహాయించి మిగతావన్నీ” అనే అవసరానికి negation రూపం సమాధానం. extglob ను ఆన్ చేయడానికి ఇదే ప్రధాన కారణం. ఇందులో రెండు విషయాలు చాలామందికి ఆశ్చర్యం కలిగిస్తాయి.

ఇది files తో పాటు directories కు కూడా సరిపోతుంది. అందువల్ల ls !(*.log) ఫలితంలో directory name కు బదులుగా ఆ directory లోని contents ను చూపిస్తుంది. పేర్లను మాత్రమే చూడటానికి ls -d లేదా printf preview ను ఉపయోగించండి.

ప్రతి ఇతర glob లాగే ఇది dot rule ను కూడా అనుసరిస్తుంది. అందువల్ల !(*.log), .log తో ముగియని ప్రతి visible name కు సరిపోతుంది. Hidden names కోసం dotglob ను కూడా సెట్ చేయాలి.

!(...) లోని ! glob negation. దీనికి history expansion మరియు bang character తో ఎలాంటి సంబంధం లేదు. అది వేరే stage లో అమలయ్యే ప్రత్యేక feature.

ఇంకో సమస్య parse time లోనే వస్తుంది. Bash పూర్తి command ను అమలు చేయడానికి ముందు parse చేస్తుంది. అందువల్ల extglob ను ఆన్ చేసి, అదే line లో extended pattern ను ఉపయోగిస్తే విఫలమవుతుంది. Option ఇంకా ఆఫ్‌లో ఉన్నప్పుడే pattern parse అవుతుంది. shopt -s extglob ను patterns కు ముందు, ప్రత్యేక line లో, script పైభాగానికి సమీపంలో ఉంచండి. Function body, function నిర్వచించినప్పుడు parse అవుతుంది. కాబట్టి call కు ముందు కాకుండా definition కు ముందే option ఆన్‌లో ఉండాలి. పై batch చేసినట్లుగా bash -O extglob తో shell ను ప్రారంభిస్తే, parsing ప్రారంభమయ్యే ముందే క్రమం సరిగ్గా అమలవుతుంది.

Shell pattern ను విస్తరిస్తుంది, command కాదు

ఇది రెండో failure mode. అనేక రకాల bugs కు ఇదే కారణం.

grep -l needle *.log
find . -name '*.log'
find . -name *.log

మొదటి పంక్తిలో matching ను bash నిర్వహిస్తుంది. grep కు filenames జాబితా అందుతుంది. రెండో పంక్తిలో pattern ను quotes లో ఉంచారు. అందువల్ల find కు *.log అనే ఐదు characters అందుతాయి. తరువాత అది starting point కింద ప్రతి depth లో తన matching ను నిర్వహిస్తుంది. మూడో పంక్తిలో bug ఉంది. bash ముందుగా current directory లో మాత్రమే pattern ను విస్తరిస్తుంది. అందువల్ల find కు ఒక నిర్దిష్ట పేరు కోసం వెతకమని చెప్పబడుతుంది. ఒక directory లో ఒక్క match మాత్రమే ఉంటే, అది తప్పు అంశం కోసం నిశ్శబ్దంగా వెతుకుతుంది. రెండు లేదా అంతకంటే ఎక్కువ matches ఉంటే, find usage error చూపిస్తుంది. అదనపు పేర్లు expression ఉండాల్సిన స్థానంలోకి వస్తాయి.

నియమం సంక్షిప్తంగా ఇది. Pattern ను command ఉపయోగించాల్సి ఉంటే, దాన్ని quotes లో ఉంచండి. Shell ఉపయోగించాల్సి ఉంటే, దాన్ని quotes లేకుండా ఉంచండి. ఇదే విభజన tar లోని --exclude patterns కు, అలాగే grep లోని rsync patterns కు వర్తిస్తుంది. grep లోని --include filters కు కూడా ఇదే నియమం వర్తిస్తుంది.

Globs regular expressions కావు, కొన్ని characters ఒకేలా ఉన్నప్పటికీ. Glob లో * అంటే characters యొక్క ఏదైనా వరుస. Regular expression లో * అంటే దాని ముందు ఉన్న అంశం zero లేదా అంతకంటే ఎక్కువ సార్లు రావడం. అందువల్ల grep '*.log', కనిపించే రూపం సూచించే దానికంటే పూర్తిగా భిన్నమైనదాన్ని కోరుతుంది.

Variables కూడా ఇదే operation order ను అనుసరిస్తాయి. Variable expansion తరువాత globbing జరుగుతుంది. అందువల్ల pattern ను కలిగి ఉన్న unquoted variable directory కు అనుగుణంగా విస్తరించబడుతుంది.

pat='*.log'
printf '%s\n' $pat
printf '%s\n' "$pat"

Quotes లేకుండా ఉంచితే, variable ఫలితంపై bash globbing చేస్తుంది. Quotes లో ఉంచితే, pattern literal గానే ఉంటుంది. దీనికి సంబంధించిన మరో ముఖ్యమైన విషయం ఉంది. Globbing ద్వారా ఉత్పత్తి అయిన words ను spaces ఆధారంగా మళ్లీ split చేయరు. అందువల్ల for f in *.log space ఉన్న filename ను ఒకే పేరుగా నిర్వహిస్తుంది. for f in $(ls *.log) మాత్రం ఆ పేరును రెండు words గా విడగొడుతుంది. Glob ను నేరుగా loop చేయండి.

విధ్వంసక pattern ను అమలు చేయడానికి ముందు దాని ప్రభావాన్ని పరిశీలించండి

కొత్త pattern తో మొదట rm ను ఎప్పుడూ అమలు చేయవద్దు. ముందుగా ఆ pattern ను ఎలాంటి నష్టం కలిగించని command తో అమలు చేసి, వచ్చిన జాబితాను చదవండి. తరువాత పంక్తి ప్రారంభంలోని command ను మాత్రమే మార్చండి.

target='!(*.log)'
printf '%s\n' $target
ls -ld -- $target
rm -- $target

pattern ను ఒకసారి target లో రాయడం వల్ల మూడు పంక్తుల్లో అది వేరువేరుగా మారకుండా ఉంటుంది. $target ను ఉద్దేశపూర్వకంగా quotes లో పెట్టలేదు, ఎందుకంటే దానివల్ల bash దాన్ని expand చేస్తుంది. printf '%s\n' ప్రతి పేరును ఒక్కో పంక్తిలో చూపిస్తుంది; ఏదీ మార్చదు. ls -ld directoryల లోపలి విషయాలను చూపకుండా ప్రతి entry ను స్వయంగా చూపిస్తుంది. mode column ఏ entries directoryలు అన్నది సూచిస్తుంది. recursive delete కు ముందు ఇదే పరిశీలించాలి. drwxr-xr-x permission bits ను చదవడం లో ఆ column గురించి వివరించబడింది.

up arrow తో మునుపటి పంక్తిని తిరిగి తెచ్చి, command ను మాత్రమే మార్చండి. అప్పుడు pattern మారదు. pattern ను జ్ఞాపకం నుంచి మళ్లీ టైప్ చేయడంలోనే పొరపాటు జరిగే అవకాశం ఎక్కువ.

pattern కు ముందు -- ను ఉంచండి. ఇది options ముగిసినట్లు సూచిస్తుంది. అందువల్ల - తో ప్రారంభమయ్యే filename ను flag గా కాకుండా పేరుగా పరిగణిస్తుంది.

స్క్రిప్ట్‌లో కొంత భాగానికి globbing ను ఆపాలంటే set -f దాన్ని disable చేస్తుంది. set +f దాన్ని మళ్లీ enable చేస్తుంది.

ఈ అలవాటు ముఖ్యమైనది, ఎందుకంటే rm కు undo లేదు. rm -rf తో తొలగించిన files ను తిరిగి పొందడం నెమ్మదిగా జరుగుతుంది మరియు సాధారణంగా పూర్తిగా సాధ్యం కాదు. అందువల్ల preview చేయడం, దాని ప్రత్యామ్నాయంతో పోలిస్తే, చాలా తక్కువ ఖర్చుతో కూడుకున్నది.

పని పూర్తయిన తర్వాత practice directory ను శుభ్రం చేయండి. path ను ముందుగా print చేసి చదవండి. ఎందుకంటే తప్పు variable కు rm -rf ను సూచించడం ఈ section వివరించే ప్రమాదమే.

cd ~
echo "$lab"
rm -rf -- "$lab"

FAQ

find . -name *.log తప్పు ఫైళ్లను ఎందుకు కనుగొంటుంది?

ఎందుకంటే find ప్రారంభమయ్యేలోపే bash, *.log ను expand చేస్తుంది. Shell ప్రస్తుత directoryకి వ్యతిరేకంగా pattern ను సరిపోల్చి, వచ్చిన filename ను find కు పంపుతుంది. ఆ తర్వాత find ప్రతి స్థాయిలో ఆ ఒక్క పేరునే వెతుకుతుంది. రెండు లేదా అంతకంటే ఎక్కువ ఫైళ్లు సరిపోతే, expression అవసరమైన చోట find కు అదనపు arguments అందుతాయి. అప్పుడు అది usage error చూపిస్తుంది. Pattern ను find . -name '*.log' గా quote చేయండి. అప్పుడు find తన స్వంత నియమాలు మరియు recursion ఉపయోగించి matching చేస్తుంది.

నా pattern literal text గా కనిపిస్తే దాని అర్థం ఏమిటి?

ఏదీ సరిపోలలేదని అర్థం. సాధారణంగా unmatched pattern ను bash అలాగే ఉంచి, raw characters ను command కు పంపుతుంది. Command వాటిని filename గా పరిగణిస్తుంది. shopt -s failglob ను set చేస్తే unmatched pattern error గా మారి command ఆగిపోతుంది. లేదా shopt -s nullglob ను set చేస్తే అది ఏమీ expand కాకుండా ఉంటుంది. nullglob ఉపయోగించినప్పుడు arguments ఏవీ లేకపోయినా command సరైనదిగా ఉందో తనిఖీ చేయండి. ఎందుకంటే ls *.nope, bare ls గా మారి మొత్తం directory ను list చేస్తుంది.

bash లో ఒక pattern మినహా ప్రతి ఫైలును ఎలా match చేయాలి?

విడిగా ఉన్న ఒక line లో shopt -s extglob ఉపయోగించి extended patterns ను enable చేయండి. తరువాత negation రూపాన్ని ఉపయోగించండి. !(*.log), .log తో ముగియని పేర్లను match చేస్తుంది. !(*.log|*.md) రెండింటినీ మినహాయిస్తుంది. dotglob కూడా set చేయకపోతే hidden files ఫలితంలో ఉండవు. Directories కూడా చేర్చబడతాయి. అందువల్ల pattern ను rm కు అందించే ముందు printf '%s\n' !(*.log) తో preview చేయండి.

* hidden files ను ఎందుకు దాటవేస్తుంది?

ప్రారంభ dot ను literal గా match చేయాలి. అందువల్ల *, dot తో ప్రారంభమయ్యే పేరును ఎప్పుడూ match చేయదు. Hidden names ను చేరుకోవడానికి .* ను ఉపయోగించండి. లేదా ప్రతి సాధారణ pattern లో వాటిని చేర్చడానికి shopt -s dotglob ను set చేయండి. dotglob ఉపయోగించినప్పుడు . మరియు .. entries ఎల్లప్పుడూ మినహాయించబడతాయి. bash 5.2 మరియు తరువాతి versions లో default గా on ఉండే globskipdots option ద్వారా అవి .* నుంచీ కూడా బయట ఉంటాయి.

** పనిచేయడానికి globstar అవసరమా?

అవును. shopt -s globstar లేకపోతే bash, ** ను సాధారణ * గా పరిగణిస్తుంది. అది ఒక directory లోపల మాత్రమే match చేసి అక్కడే ఆగిపోతుంది. globstar on లో ఉన్నప్పుడు, మొత్తం path component గా ఉన్న ** ఏ depth లోనైనా match అవుతుంది. అందువల్ల **/*.log ప్రస్తుత directory మరియు దాని కింద ఉన్న ప్రతి subdirectory ని చేరుతుంది. **/ ఒక్కటే ఉన్నప్పుడు directories ను మాత్రమే match చేస్తుంది. ** directories కు symbolic links ను follow చేయదని గుర్తుంచుకోండి. Symlinks తో నిర్మించిన tree కోసం find -L ను ఉపయోగించండి.

#bash#globbing#shell#linux#scripting