Skip to content
C.W.K.
Stream
Lesson 01 of 05 · published

Brace Expansion and Globbing Advanced

~10 min · brace, glob, extglob

Level 0Window Tourist
0 XP0/95 lessons0/14 achievements
0/100 XP to next level100 XP to go0% complete

Brace expansion — text generation

echo {a,b,c}.txt          # a.txt b.txt c.txt
echo {1..5}                # 1 2 3 4 5
echo {01..05}              # 01 02 03 04 05  (zero-padded)
echo {1..10..2}            # 1 3 5 7 9       (step)
echo {a..e}                # a b c d e
mkdir -p project/{src,test,docs}/{2025,2026}

Brace expansion happens before glob expansion and runs even on paths that don't exist — perfect for creating directory trees.

Recursive globbing

ls **/*.py                # zsh; in bash, first enable: shopt -s globstar
ls src/**/*.{ts,tsx}       # combined with brace

** matches across directory boundaries — way faster than find -name '*.py' for everyday cases.

zsh glob qualifiers

ls *(.)                   # plain files only
ls *(/)                   # directories only
ls *(.om)                 # plain files, ordered by mtime newest first
ls *(.OL[1,5])            # 5 largest plain files
ls *(.m-1)                # plain files modified in the last day

zsh-specific. Compact and astonishingly powerful for one-liners.

extglob (bash)

shopt -s extglob
ls !(*.txt)                # everything except .txt
ls @(foo|bar).log          # exactly foo.log or bar.log
ls *(foo|bar)              # zero or more occurrences

bash equivalent of zsh's pattern alternation. Off by default, hence shopt -s extglob.

Execute the expansion order in your head

Brace expansion generates text before pathname matching. Quoting, shell options, and the current directory then determine whether patterns expand, remain literal, or fail.

No-match behavior differs by shell

Bash and zsh can treat an unmatched pattern differently, and their options can change that behavior again. Test the target shell and handle an empty match set explicitly before a state-changing loop.

Code

Build a project skeleton in one line·bash
mkdir -p project/{src,tests,docs}/{python,rust}
find project -type d

External links

Exercise

Run mkdir -p sandbox/{a,b,c}/{1,2,3}; tree sandbox. Then ls sandbox/**/* (zsh). Find your 5 biggest python files: ls -lh **/*.py(.OL[1,5]).

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.