Mengetik nama file satu per satu membuat perintah seperti cp dan rm kehilangan daya gunanya. Kabar baiknya, shell punya mekanisme menuliskan sekali dan mengenai banyak file sekaligus: globbing — pola wildcard yang diganti shell menjadi daftar nama file sebelum perintahnya berjalan. Pada Chapter ini kita akan menguasai pola *, ?, [ab], [a-z], dan [!a], membuktikan bahwa penggantian itu terjadi di shell, lalu memisahkan dua hal yang sering tertukar: globbing milik shell dan regex milik program seperti grep.

Globbing terjadi di shell, sebelum perintah berjalan #

Mekanisme globbing penting dipahami dari sumbernya: ketika kita menekan Enter, shell memindai setiap kata pada baris perintah; kata yang memuat pola wildcard diganti menjadi daftar nama file yang cocok, dan perintah hanya menerima daftar jadi itu. Perintah ls atau rm tidak pernah tahu bahwa kita mengetik pola — keduanya seolah diberi nama-nama file satu per satu. Mari kita buktikan dengan echo:

bash
touch laporan.txt laporan-2024.txt laporan.md data1.txt data2.txt
echo la*
echo *.md

Output yang Dihasilkan:

text
laporan-2024.txt laporan.md laporan.txt
laporan.md

Mari kita telaah hasilnya:

  1. Baris 1 (touch ...): membuat lima file kosong sebagai fixture latihan.
  2. Baris 2 (echo la*): pola la* diganti shell menjadi setiap nama file berawalan la — hasilnya laporan-2024.txt, laporan.md, dan laporan.txt dalam urutan abjad, dan echo tinggal mencetaknya.
  3. Baris 3 (echo *.md): pola *.md berarti nama apa pun yang berakhiran .md; hanya laporan.md yang lolos.

Tanda * cocok dengan teks sepanjang apa pun, termasuk kosong, tetapi satu pengecualian menempel padanya: * tidak pernah mencocokkan nama yang diawali titik, karena file tersembunyi memang sengaja dikeluarkan dari globbing. Nama .bashrc hanya bisa dijangkau pola yang berawalan titik, misalnya .*. Uraian globbing di bash yang paling lengkap tersedia pada BashGuide: glob .

Pola ?, [set], [rentang], dan [!set] #

Wildcard lain membidik satu karakter saja, dan ini membuatnya lebih presisi. Tanda ? mewakili tepat satu karakter; [ab] mewakili satu karakter dari himpunan itu; [a-z] mewakili satu karakter dari rentang; dan [!a] berarti satu karakter di luar himpunan. Ringkasannya:

PolaCocok dengan satu karakter yang
*bagian nama sepanjang apa pun (nol karakter pun boleh)
?apa pun, tepat satu
[12]angka 1 atau 2
[a-c]huruf a, b, atau c
[!r]apa pun selain huruf r

Mari kita uji keempatnya sekaligus:

bash
touch file1.txt file2.txt file10.txt rapor-a.txt rapor-b.txt rapor-c.txt
ls file?.txt
echo rapor-[ac].txt
echo rapor-[a-c].txt
echo [!r]*

Output yang Dihasilkan:

text
file1.txt
file2.txt
rapor-a.txt rapor-c.txt
rapor-a.txt rapor-b.txt rapor-c.txt
file1.txt file10.txt file2.txt

Hasilnya menunjukkan presisi tiap pola. Pola file?.txt menemukan file1.txt dan file2.txt tetapi tidak file10.txt, karena ? hanya mewakili satu karakter sedangkan 10 terdiri dari dua. Pola rapor-[ac].txt memilih dua dari tiga rapor, rapor-[a-c].txt mengambil semuanya, dan [!r]* mengambil semua nama yang huruf pertamanya bukan r. Hasil ls file?.txt pun tercetak satu per baris, seperti bila kedua nama ditulis manual sebagai dua argument.

Saat pola tidak menemukan lawan #

Apa yang terjadi bila pola tidak cocok dengan satu nama pun? Jawaban bash bawaan sering mengejutkan pemula: pola dibiarkan apa adanya, sebagai teks biasa. Blok berikut sekaligus memperlihatkan daftar yang sebenarnya dikirim shell ke sebuah perintah:

bash
touch laporan.txt data1.txt data2.txt
echo zzz*
set -- *.txt
printf '%s\n' "$@"

Output yang Dihasilkan:

text
zzz*
data1.txt
data2.txt
laporan.txt

Mari kita telaah baris-baris di atas:

  1. Baris 2 (echo zzz*): tidak ada file berawalan zzz, jadi shell mengirim teks zzz* apa adanya kepada echo — bukan pesan error, bukan daftar kosong.
  2. Baris 3 (set -- *.txt): pola *.txt diganti menjadi data1.txt, data2.txt, laporan.txt; perintah set -- kemudian memasang ketiga nama itu sebagai positional parameter $1, $2, $3 — cara paling langsung untuk “menangkap” hasil globbing.
  3. Baris 4 (printf '%s\n' "$@"): mencetak setiap parameter di barisnya sendiri — inilah daftar yang diterima sebuah perintah ketika kita menulis ls *.txt.

Karena pola yang tidak ketemu lolos sebagai teks, typo seperti rm*.tmp (tanpa spasi) membuat rm menerima nama file literal rm*.tmp, bukan semua file berakhiran .tmp yang kita maksud. Biasakan menguji pola dengan echo dulu sebelum dipasang pada perintah yang mengubah atau menghapus.

Globbing shell bukan regex #

Dunia pencocokan pola punya dua bahasa yang berbeda, dan keduanya sering ditulis dengan tanda-tanda yang mirip. Globbing adalah bahasa shell untuk nama file, dan regex (regular expression) adalah bahasa untuk isi teks yang dipakai program seperti grep. Perbedaan mendasarnya: globbing mengharuskan pola cocok pada keseluruhan nama file, sedangkan regex dianggap cocok bila ditemukan di mana pun di dalam sebuah baris. Pola ab* adalah contoh sempurna dua bahasa itu:

bash
touch ab abb a
echo ab*
printf 'a\nab\nabb\nbata\n' > kata.txt
grep 'ab*' kata.txt

Output yang Dihasilkan:

text
ab abb
a
ab
abb
bata

Perhatikan perbedaannya pada pola yang tertulis sama. Di shell, ab* berarti “nama berawalan ab” — hanya ab dan abb cocok. Di regex, ab* berarti “huruf a diikuti nol atau lebih huruf b” — tanda bintang menempel pada huruf sebelumnya. Karena itu grep 'ab*' juga menemukan baris a (banyaknya b boleh nol) dan bata (huruf a tanpa b setelahnya pun lolos). Satu pola, dua bahasa, dua hasil.

Dengan wildcard, satu baris perintah kini bekerja untuk sekumpulan file sekaligus. Keterampilan penutup yang membuat semua ini makin cepat adalah memanfaatkan riwayat perintah yang telah kita ketik — materi Chapter Command History.