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:
touch laporan.txt laporan-2024.txt laporan.md data1.txt data2.txt
echo la*
echo *.mdOutput yang Dihasilkan:
laporan-2024.txt laporan.md laporan.txt
laporan.mdMari kita telaah hasilnya:
- Baris 1 (
touch ...): membuat lima file kosong sebagai fixture latihan. - Baris 2 (
echo la*): polala*diganti shell menjadi setiap nama file berawalanla— hasilnyalaporan-2024.txt,laporan.md, danlaporan.txtdalam urutan abjad, danechotinggal mencetaknya. - Baris 3 (
echo *.md): pola*.mdberarti nama apa pun yang berakhiran.md; hanyalaporan.mdyang 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:
| Pola | Cocok 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:
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:
file1.txt
file2.txt
rapor-a.txt rapor-c.txt
rapor-a.txt rapor-b.txt rapor-c.txt
file1.txt file10.txt file2.txtHasilnya 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:
touch laporan.txt data1.txt data2.txt
echo zzz*
set -- *.txt
printf '%s\n' "$@"Output yang Dihasilkan:
zzz*
data1.txt
data2.txt
laporan.txtMari kita telaah baris-baris di atas:
- Baris 2 (
echo zzz*): tidak ada file berawalanzzz, jadi shell mengirim tekszzz*apa adanya kepadaecho— bukan pesan error, bukan daftar kosong. - Baris 3 (
set -- *.txt): pola*.txtdiganti menjadidata1.txt,data2.txt,laporan.txt; perintahset --kemudian memasang ketiga nama itu sebagai positional parameter$1,$2,$3— cara paling langsung untuk “menangkap” hasil globbing. - Baris 4 (
printf '%s\n' "$@"): mencetak setiap parameter di barisnya sendiri — inilah daftar yang diterima sebuah perintah ketika kita menulisls *.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:
touch ab abb a
echo ab*
printf 'a\nab\nabb\nbata\n' > kata.txt
grep 'ab*' kata.txtOutput yang Dihasilkan:
ab abb
a
ab
abb
bataPerhatikan 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.