Sintaks Bash punya banyak sudut: variabel spesial yang isinya diisi otomatis oleh shell, operator test satu-dua huruf, ekspansi parameter, sampai trap untuk signal. Materinya tersebar di tujuh belas chapter Section Shell dan Scripting
, dan saat sedang menulis skrip kita jarang membutuhkan semuanya sekaligus — biasanya cukup mengingat bentuk $@ atau arti -z. Chapter ini adalah kartu rujukan untuk momen-momen itu: tabel-tabel ringkas untuk sintaks yang sering dicari, ditutup empat idiom pembuka skrip yang sudah teruji. Setiap tabel menautkan kembali ke chapter yang membahasnya tuntas.
Variabel Spesial Bash #
Shell mengisi beberapa variabel secara otomatis setiap kali skrip berjalan. Variabel-variabel ini hanya satu-dua karakter dan hampir selalu muncul di skrip yang membaca argumen atau memeriksa keberhasilan perintah. Tabel berikut merangkum tujuh di antaranya yang paling sering dipakai.
| Variabel | Isi | Contoh pemakaian |
|---|---|---|
$0 | Nama skrip saat dipanggil | Pesan cara pakai: "pakai: $0 <file>" |
$# | Jumlah argumen | Validasi input di awal skrip |
$1, $2, … | Argumen ke-1, ke-2, dan seterusnya | Mengambil parameter posisi |
$@ | Seluruh argumen, terpisah per kata | Iterasi: for f in "$@" |
$? | Exit code perintah terakhir | if ! grep -q pola file; then ... |
$$ | PID skrip yang sedang berjalan | Membuat nama file lock yang unik |
$! | PID proses background terakhir | kill "$!" menghentikan job |
Dua variabel terakhir, $$ dan $!, berisi process ID sehingga nilainya berbeda pada setiap eksekusi — itulah alasan demo di bawah sengaja tidak mencetak keduanya. Lima variabel lainnya bisa diperlihatkan dengan skrip pendek:
cat > demo-arg.sh <<'BATEK'
#!/usr/bin/env bash
# demo-arg.sh — memperlihatkan variabel spesial saat skrip dipanggil
echo "nama skrip \$0 -> $0"
echo "jumlah arg. \$# -> $#"
echo "semua arg. \$@ -> $@"
echo "arg pertama \$1 -> $1"
exit 5
BATEK
bash demo-arg.sh backup harian
echo "exit code \$? -> $?"Output yang Dihasilkan:
nama skrip $0 -> demo-arg.sh
jumlah arg. $# -> 2
semua arg. $@ -> backup harian
arg pertama $1 -> backup
exit code $? -> 5Mari kita bedah baris per barisnya:
- Baris 1–9 (heredoc
cat > demo-arg.sh): menulis skrip demo ke file. Tanda kutip pada<<'BATEK'membuat isi heredoc disalin apa adanya, sehingga\$0tetap tertulis begitu di file dan baru dievaluasi ketika skrip demo berjalan — hasilnya, layar menampilkan label$0sekaligus nilainya. - Baris 10 (
bash demo-arg.sh backup harian): menjalankan skrip dengan dua argumen. Shell mengisi$0dengandemo-arg.sh,$#dengan angka 2,$@dengan kedua argumen, dan$1dengan argumen pertama; barisexit 5menutup skrip dengan exit code 5. - Baris 11 (
echo "exit code ..."): mencetak$?sesaat setelahbashselesai — nilainya 5, warisanexit 5dari dalam skrip demo, dan inilah mekanisme yang dipakaiifuntuk menilai keberhasilan setiap perintah.
Pembahasan penuh variabel spesial ada di chapter Arguments dan Command Line Options .
Operator Test untuk Kondisi #
Konstruksi [ ... ] (perintah test) menilai kondisi lewat operator yang bentuknya satu-dua huruf. Ringkas, tetapi mudah tertukar antara operasi string dan operasi angka. Tabel berikut memisahkan keduanya.
| Operator | Menguji apa | Contoh yang benar |
|---|---|---|
-f | File ada dan berupa file biasa | [ -f /etc/hosts ] |
-d | Direktori ada | [ -d /etc ] |
-e | Ada, jenis apa pun | [ -e /dev/sda ] |
-z | String kosong | [ -z "$nama" ] |
-n | String tidak kosong | [ -n "$nama" ] |
= | Dua string sama | [ "$jawab" = "ya" ] |
!= | Dua string berbeda | [ "$jawab" != "ya" ] |
-eq, -ne | Angka sama, angka berbeda | [ "$sisa" -eq 0 ] |
-lt, -gt | Angka lebih kecil, lebih besar | [ "$umur" -gt 17 ] |
-le, -ge | Angka lebih kecil atau sama, lebih besar atau sama | [ "$sisa" -le 3 ] |
String memakai = sedangkan angka memakai -eq; [ "5" = "05" ] bernilai salah karena keduanya dibandingkan sebagai teks, bukan sebagai bilangan. Kutip ganda pada "$var" juga bukan hiasan:
Ekspansi Parameter #
Ekspansi parameter memproses isi variabel tanpa perintah eksternal. Empat bentuk pertama tabel berikut memberi nilai bawaan dan membaca panjang string; empat bentuk berikutnya memotong isi variabel dari depan atau belakang.
| Ekspansi | Hasil | Contoh |
|---|---|---|
${var:-bawaan} | Nilai var, atau bawaan bila kosong | ${user:-budi} |
${var:=bawaan} | Sama seperti di atas, sekaligus mengisi var | ${user:=budi} |
${#var} | Panjang string | ${#teks} |
${var/pola/baru} | Mengganti kemunculan pertama | ${teks/kucing/anjing} |
${var#pola} | Buang kecocokan terpendek dari depan | ${file#*/} |
${var##pola} | Buang kecocokan terpanjang dari depan | ${path##*/} |
${var%pola} | Buang kecocokan terpendek dari belakang | ${file%.tar.gz} |
${var%%pola} | Buang kecocokan terpanjang dari belakang | ${url%%/*} |
Contoh klasiknya adalah mengurai nama file. Dua ekspansi pertama di bawah sering dipakai berpasangan saat memproses arsip, dan ${#var} menghitung panjang nama tanpa perintah wc:
file="laporan-2026.tar.gz"
echo "${file#*-}"
echo "${file%.tar.gz}"
echo "${#file}"Output yang Dihasilkan:
2026.tar.gz
laporan-2026
19Mari kita bedah baris per barisnya:
- Baris 1 (
file="laporan-2026.tar.gz"): menyiapkan satu nama file arsip sebagai bahan ekspansi. - Baris 2 (
echo "${file#*-}"): membuang semua karakter sampai tanda hubung pertama, sehingga yang tersisa2026.tar.gz. - Baris 3 (
echo "${file%.tar.gz}"): membuang akhiran arsip dari belakang, sehingga yang tersisalaporan-2026. - Baris 4 (
echo "${#file}"): mencetak panjang stringfiledalam satuan karakter — sembilan belas.
Dua hasil pertama adalah pasangan klasik saat memproses arsip: nama dasar dan akhiran file dipisahkan tanpa perintah eksternal. Materi tuntasnya ada di chapter Variables dan Quoting .
Trap dan Signal yang Sering Ditangkap #
Skrip yang rapi membersihkan jejaknya sendiri: file sementara dihapus, kunci dilepas, pesan penutup dicetak — lewat jalur keluar mana pun skrip berakhir. Perintah trap mendaftarkan aksi untuk sebuah signal, dan tabel berikut merangkum signal yang paling relevan bagi penulis skrip.
| Signal | Nama | Pemicu umum |
|---|---|---|
0 | EXIT | Skrip selesai, lewat jalur mana pun |
1 | HUP | Terminal ditutup; daemon diminta memuat ulang konfigurasi |
2 | INT | Ctrl+C ditekan |
3 | QUIT | Ctrl+\ ditekan |
15 | TERM | kill tanpa opsi — permintaan berhenti yang sopan |
9 | KILL | Paksaan dari kernel; proses dihentikan seketika |
Signal KILL (9) istimewa: proses tidak pernah menerima signal ini karena kernel yang langsung menghentikannya — sehingga tidak ada trap, tidak ada pembersihan. Urutan yang benar karena itu adalah kill dulu (TERM), beri waktu, dan kill -9 hanya sebagai upaya terakhir. Pembahasan penuhnya ada di chapter Signals dan Traps
.
Idiom Skrip yang Sudah Teruji #
Empat potongan berikut bukan teori, melainkan kerangka pembuka yang dipakai hampir semua skrip serius. Masing-masing menyelesaikan satu masalah klasik. Idiom pertama, mode ketat — tiga baris ini layak menjadi kebiasaan untuk semua skrip di atas sepuluh baris:
#!/usr/bin/env bash
set -euo pipefailOpsi -e menghentikan skrip saat ada perintah gagal, -u menjadikan pemakaian variabel kosong sebagai error, dan -o pipefail membuat pipeline melaporkan kegagalan dari tahap mana pun, bukan hanya tahap terakhir. Tanpa ketiganya, skrip terus berjalan dalam kondisi setengah rusak dan gagal jauh dari akar masalahnya.
Idiom kedua, parsing argumen dengan while dan case:
verbose=0
while [ $# -gt 0 ]; do
case "$1" in
-v|--verbose) verbose=1 ;;
-h|--help) echo "pakai: $0 [-v] <berkas>"; exit 0 ;;
--) shift; break ;;
*) berkas="$1" ;;
esac
shift
doneSetiap putaran memeriksa satu argumen, lalu shift membuangnya sehingga $1 selalu menunjuk argumen berikutnya. Pola --) menghentikan pemrosesan opsi — semua argumen setelahnya diperlakukan sebagai berkas, mengikuti konvensi perintah Unix.
Idiom ketiga, file sementara yang pasti dibersihkan:
tmpdir=$(mktemp -d)
trap 'rm -rf "$tmpdir"' EXITmktemp -d membuat folder unik di bawah /tmp, dan trap ... EXIT memastikan folder itu terhapus baik skrip selesai normal maupun terhenti di tengah jalan. Kombinasi ini menghapus kelas bug “file sisa dari eksekusi yang gagal kemarin”.
Idiom keempat, kunci agar hanya satu instance berjalan — penting untuk skrip terjadwal yang bisa tumpang tindih:
exec 9>/tmp/backup-budi.lock
flock -n 9 || { echo "backup lain sedang berjalan"; exit 1; }flock mengunci file descriptor 9, dan opsi -n membuatnya langsung gagal ketika instance lain sudah memegang kunci. Skrip kedua keluar dengan pesan alih-alih menggandakan pekerjaan yang sama. Kumpulan praktik terkurasi untuk topik-topik semacam ini tersedia di BashFAQ
, dan rujukan resmi kelengkapannya di halaman manual bash(1)
.
Kartu rujukan di atas cukup menjadi bekal menulis skrip sehari-hari. Sintaks hanyalah separuh cerita — chapter berikutnya berpindah ke situasi ketika semuanya justru sedang rusak: peta gejala, kemungkinan, dan perintah diagnosis untuk lima area masalah yang paling sering dijumpai.