Globbing & Brace Expansion
Shell melakukan banyak ekspansi pada sebuah perintah sebelum dijalankan. Dua yang paling berguna sehari-hari: glob (match nama file) dan brace expansion (generate string).
Glob Patterns Dasar
Glob bukan regex — sintaksnya lebih sederhana, khusus untuk match nama file:
| Pattern | Arti | Contoh match |
|---|---|---|
* |
Nol atau lebih karakter apa pun | *.js → app.js, util.js |
? |
Tepat satu karakter | file?.txt → file1.txt, fileA.txt |
[abc] |
Salah satu dari a, b, atau c | [tT]est.js → test.js, Test.js |
[a-z] |
Range karakter | [0-9]*.log → 1.log, 2024.log |
[!abc] / [^abc] |
BUKAN a, b, atau c | [!_]*.md → semua .md kecuali yang diawali _ |
ls *.js # semua file .js
ls src/*.{js,ts} # js dan ts di src
ls [A-Z]* # file yang dimulai huruf kapital
ls test?.log # test1.log, testA.log (tepat 1 karakter)
ls [!.]* # semua file yang TIDAK dimulai titik
Extglob — Glob Extended
Bash menyediakan pattern lebih kuat via shopt -s extglob:
shopt -s extglob # aktifkan (biasanya sudah aktif di zsh)
ls ?(pattern) # 0 atau 1 kali → file, files
ls *(pattern) # 0 atau lebih → (mirip *)
ls +(pattern) # 1 atau lebih → minimal 1
ls @(a|b|c) # tepat satu dari → a, b, atau c
ls !(pattern) # apa pun KECUALI pattern
ls !(node_modules) # semua kecuali node_modules
ls *.@(jpg|png|gif) # gambar saja
ls +([0-9]).txt # file yang nama-nya hanya angka
rm !(*.md|*.txt) # hapus semua kecuali md dan txt
Recursive Glob (**)
Untuk match file di semua subdirektori sekaligus:
# Bash: aktifkan globstar dulu
shopt -s globstar
ls **/*.js # semua .js rekursif
grep "TODO" **/*.py # cari TODO di semua .py
- zsh:
**aktif default. - Tanpa
globstar,**di bash sama seperti*.
Brace Expansion
Berbeda dari glob, brace expansion men-generate string — tidak peduli file-nya ada atau tidak.
echo {a,b,c} # a b c
echo img.{jpg,png,gif} # img.jpg img.png img.gif
# Range angka
echo {1..5} # 1 2 3 4 5
echo {10..1} # 10 9 8 7 ... 1 (reverse)
echo {1..10..2} # 1 3 5 7 9 (step 2)
# Zero-padded
echo {01..05} # 01 02 03 04 05
echo {001..100} # 001 002 ... 100
# Range huruf
echo {a..e} # a b c d e
# Nested braces
echo {a,b}-{1,2} # a-1 a-2 b-1 b-2
mkdir -p project/{src,tests,docs}/{js,css}
# → project/src/js, project/src/css, project/tests/js, ...
Brace expansion + glob sangat kuat:
# Backup file konfigurasi
cp config.json{,.bak}
# → cp config.json config.json.bak (comma kosong = "" di ujung)
# Batch rename (lewat mv + brace)
mv foto-{01..10}.jpg arsip/
# Buat 5 file log kosong
touch log-{1..5}.txt
# Copy pattern
cp app.{html,css,js} dist/
Urutan Ekspansi (Penting!)
Shell meng-expand dalam urutan tetap — paham urutan ini menjelaskan banyak perilaku membingungkan:
Konsekuensi:
# Brace (1) dulu, baru glob (7) — jadi brace JALAN walau file tidak ada
echo file.{jpg,png} # → file.jpg file.png (tetap walau file tidak ada)
# Glob (7) paling akhir — kalau tidak ada match, pattern tetap literal
ls *.tidak-ada-extension # ls: *.tidak-ada-extension: No such file or directory
# Variable (3) sebelum glob (7)
FILES="*.js"
ls $FILES # $FILES di-expand ke *.js, lalu glob match
Quoting — Mematikan Ekspansi
"double quotes"— mematikan glob, brace, word split; tidak mematikan variable & command substitution.'single quotes'— mematikan semua ekspansi, paling literal.- Tanpa quote — semua ekspansi aktif.
echo "File: $USER" # File: budi
echo 'File: $USER' # File: $USER (literal)
echo {1..3} # 1 2 3
echo "{1..3}" # {1..3} (brace mati di dalam ")
Tips
- Test dulu dengan
echo— sebelumrmataumv, jalankanechountuk lihat hasil ekspansi. - Gunakan brace untuk batch operasi —
mv foto-{01..20}.jpg arsip/jauh lebih singkat dari loop. - Aktifkan
globstardi~/.bashrcagar**berfungsi —shopt -s globstar. - Kutip variabel yang mungkin berisi spasi —
"$filename"bukan$filename.