Belajar BASH Scripting - Perulangan Bagian 2: while, until & Membaca File
Episode 12 of 27

Belajar BASH Scripting - Perulangan Bagian 2: while, until & Membaca File

Melanjutkan perulangan dengan `while` yang berjalan selama kondisi benar, `until` yang berjalan sampai kondisi terpenuhi, dan pola `while true` untuk daemon. Dibahas pula membaca file baris demi baris dengan `while read -r line`, pengolahan CSV, serta jebakan subshell yang membuat variabel "hilang" setelah pipeline.

AI Agent
AI AgentAugust 2, 2026
0 views
7 min read

Pendahuluan

Setelah di episode 11 sebelumnya kita menguasai perulangan for — dari daftar kata, rentang {1..10}, hingga C-style for ((i=0; i<10; i++)) — pada episode kali ini kita melengkapi gudang perulangan dengan pasangannya: while dan until.

for itu seperti tukang sortir di pabrik yang tahu persis berapa kotak akan lewat: ia butuh daftar lengkap sebelum mulai. Tapi ada banyak pekerjaan yang tidak tahu berapa kali harus diulang sebelum selesai — menunggu service hidup, membaca file yang barisnya bisa bertambah, atau menunggu pengguna mengetik jawaban yang benar. Untuk pekerjaan seperti ini, while dan until adalah alat yang tepat: mereka mengulang selama sebuah kondisi terpenuhi, bukan selama ada item tersisa.

Bonus terbesar episode ini: membaca file baris demi baris dengan while read. Hampir semua script operasional — parser log, pengolahan file konfigurasi, pemrosesan CSV — bertumpu pada pola ini. Kita juga akan membedah salah satu misteri paling terkenal di Bash: mengapa variabel di dalam while sering "hilang" setelah pipeline selesai (jawabannya: subshell). Mari mulai.

Pembahasan Utama

while: Mengulang Selama Kondisi Benar

while adalah perulangan yang paling fleksibel. Ia mengevaluasi sebuah kondisi — perintah atau test apa pun — dan selama kondisi itu mengembalikan exit status 0 (sukses), blok do...done terus dijalankan:

Struktur dasar while
count=0
while [ "$count" -lt 5 ]; do
    echo "Hitungan: $count"
    count=$((count + 1))
done
Selama count < 5, blok terus dijalankan

Bacaan kode di atas: "selama $count kurang dari 5, cetak nilainya lalu tambah 1." Tanpa baris count=$((count + 1)), kondisi tidak akan pernah berubah dan kalian terjebak infinite loop. Ini kesalahan klasik — kondisi dan perubahan kondisi adalah dua hal yang harus selalu ada bersama dalam perulangan berbasis kondisi.

Analogikan while dengan tungku penjaga di kamp: api dibiarkan menyala selama kayu masih ada ([ -n "$kayu" ]). Setiap iterasi kalian memeriksa kayu, dan ketika habis, api padam. Bash sendiri yang mengevaluasi kondisi di awal setiap iterasi — sebelum blok dieksekusi.

until: Mengulang Sampai Kondisi Benar

until adalah kebalikan logis dari while — ini bukan sekadar kosmetik, melainkan perbedaan cara berpikir:

  • while [ kondisi ] → jalankan selama kondisi benar.
  • until [ kondisi ] → jalankan sampai kondisi benar (berhenti begitu benar).
until menjalankan selama kondisi salah
count=0
until [ "$count" -ge 5 ]; do
    echo "Masih di angka $count"
    count=$((count + 1))
done
Berhenti ketika count mencapai 5

Secara hasil, contoh di atas identik dengan versi while. Perbedaannya pada keterbacaan: pilih until ketika kondisi berhenti lebih natural untuk diucapkan daripada kondisi lanjut. Bayangkan menunggu pengguna menjawab "ya":

Menunggu konfirmasi dengan until
jawaban=""
until [ "$jawaban" = "ya" ]; do
    read -p "Konfirmasi (ketik 'ya'): " jawaban
done
echo "Dikonfirmasi!"
Loop berhenti begitu jawaban ya, tidak peduli berapa kali ditanya

Bacaan mentalnya: "tanyai terus sampai dia menjawab ya." Jauh lebih mudah dibaca daripada while [ "$jawaban" != "ya" ] yang memaksa kalian berpikir dalam negasi.

Pola while true + break: Daemon Ringan

Ada satu pola yang sangat populer di script daemon dan watcher: while true — perulangan yang tidak pernah berhenti secara alami, dan dihentikan secara eksplisit lewat break dari dalam. Pola ini cocok ketika kondisi berhenti sulit ditulis di bagian atas loop (misalnya tergantung hasil kerja iterasi):

Pola while true dengan break
while true; do
    if [ -f /tmp/stop-dengan-fresh ]; then
        echo "File penanda terdeteksi, berhenti."
        break
    fi
    echo "Menjalankan tugas rutin... (Ctrl+C untuk berhenti)"
    sleep 10
done
Daemon sederhana yang berhenti bila file penanda muncul

Perintah true adalah perintah bawaan Bash yang selalu mengembalikan exit status 0 — kondisi yang tak pernah salah, sehingga loop tak pernah berhenti oleh kondisinya sendiri. Di dalamnya, break menjadi satu-satunya jalan keluar yang disengaja. Pola ini juga sering menampung continue untuk melompati satu siklus:

while true dengan continue dan break
while true; do
    read -p "Perintah: " cmd
    case "$cmd" in
        next)   continue ;;
        quit)   break ;;
        *)      echo "Eksekusi: $cmd" ;;
    esac
done
echo "Selesai."
continue melewatkan siklus, break mengakhiri semuanya

Note

Kombinasi case (episode 10) + while true + break membentuk inti dari hampir semua interactive REPL dan menu loop di script Bash. Pola ini juga dasar dari script watchdog yang memantau proses dan me-restart-nya bila mati. Hafalkan polanya: while true untuk siklus abadi, case untuk menerjemahkan input, continue/break untuk kendali keluar.

Membaca File Baris demi Baris

Sekarang kita masuk ke pola paling penting di episode ini. Untuk memproses sebuah file baris demi baris, formula standarnya adalah:

Membaca file baris demi baris
while read -r line; do
    echo "Baris: $line"
done < file.txt
while read -r line; do ... done < file.txt

Mari bedah setiap bagiannya:

  1. while read -r line — setiap iterasi, perintah read mengambil satu baris dari stdin dan menyimpannya ke variabel line, lalu mengembalikan exit status 0 (berhasil membaca). Ketika file habis, read mengembalikan status non-0 dan loop berhenti. Keindahan pola ini: loop tahu berhenti sendiri, tanpa menghitung baris.
  2. done < file.txt — redirection input menempel di done, bukan di awal. Ini memberitahu: "pasok setiap baris file.txt sebagai stdin untuk perintah read di dalam loop."

Faktanya, read adalah kunci di sini — setiap iterasi ia melahap satu baris dan menggeser kursor ke baris berikutnya. Ini seperti ban berjalan tempat kalian mengambil satu lembar dokumen setiap kali sampai tumpukan habis.

Kenapa Harus read -r?

Opsi -r pada read mungkin tampak sepele, tetapi ia menyelamatkan kalian dari bug yang sangat halus. Tanpa -r, read memperlakukan backslash (\) sebagai escape character — karakter yang memodifikasi karakter berikutnya:

Pengaruh -r pada backslash
echo 'C:\data\server\logs.txt' > path.txt
 
read path < path.txt
echo "Tanpa -r : $path"
# Tanpa -r : C:dataserverlogs.txt   <- backslash hilang!
 
read -r path < path.txt
echo "Dengan -r: $path"
# Dengan -r: C:\data\server\logs.txt
Tanpa -r, backslash di file dicerna sebagai escape

Mengapa read tanpa -r menghilangkan backslash? Karena read dirancang untuk mendukung line continuation — backslash di akhir baris berarti "sambung dengan baris berikutnya". Tanpa -r, backslash di tengah baris pun ikut dicerna. Untuk data dunia nyata — path Windows, regex, escape sequence — backslash adalah data yang sah dan harus dipertahankan. Aturan emasnya: selalu tulis read -r kecuali kalian punya alasan eksplisit untuk tidak melakukannya.

IFS untuk Menjaga Spasi di Awal Baris

Ada jebakan kedua yang lebih samar: read secara default menghilangkan spasi dan tab di awal dan akhir baris. Ini karena IFS (Internal Field Separator) default berisi spasi, tab, dan newline. Untuk file yang barisnya sengaja memiliki spasi pembuka (misalnya kode sumber atau output yang diindentasi), gunakan IFS= sebelum read:

IFS kosong menjaga spasi pembuka
while IFS= read -r line; do
    echo ">>> $line <<<"
done < indentasi.txt
IFS= membuat spasi awal baris tetap utuh

Perhatikan penulisannya: while IFS= read -r line — penugasan IFS= langsung di baris yang sama dengan read. Ini adalah penugasan variabel satu-perintah (command assignment), yang hanya berlaku untuk satu perintah tersebut. Dengan IFS kosong, read tidak memotong karakter spasi mana pun dari baris.

Important

Selalu pasangkan read dengan -r, dan gunakan IFS= bila baris-baris file mengandung spasi pembuka yang harus dipertahankan. Rumus lengkap yang aman untuk hampir semua file: while IFS= read -r line; do ...; done < file. Ketiga elemen — IFS=, read -r, dan done < file — adalah paket yang tidak bisa dicicil: mengurangi salah satunya berarti menunda bug aneh yang hanya muncul pada data tertentu.

Membaca CSV: while IFS=',' read -r f1 f2

Keunggulan read yang paling sering dipakai di dunia nyata adalah kemampuannya memecah satu baris menjadi beberapa field sekaligus. Cukup beri tahu read daftar variabel — ia membagi baris berdasarkan IFS dan mengisi masing-masing variabel:

Membaca CSV dengan pemisah koma
while IFS=',' read -r nama umur kota; do
    echo "Nama : $nama"
    echo "Umur : $umur"
    echo "Kota : $kota"
    echo "---"
done < data.csv
Baris 'arman,30,jakarta' terpecah jadi tiga variabel

Untuk setiap baris seperti arman,30,jakarta, read memecahnya berdasarkan koma dan mengisi $nama=arman, $umur=30, $kota=jakarta. Jika sebuah baris memiliki field lebih sedikit dari jumlah variabel, sisanya kosong; jika lebih banyak, field terakhir menampung sisanya.

Contoh lebih dekat dengan dunia DevOps: file servers.csv berisi daftar server dan perannya, lalu script melakukan ping ke semuanya:

Ping massal dari CSV
while IFS=',' read -r host role; do
    if ping -c 1 -W 2 "$host" >/dev/null 2>&1; then
        echo "OK   : $host ($role)"
    else
        echo "FAIL : $host ($role)"
    fi
done < servers.csv
Setiap baris CSV menjadi satu target ping

Tip

Untuk CSV dengan baris kosong atau komentar (baris diawali #), tambahkan filter di awal blok: [[ -z "$host" || "$host" == \#* ]] && continue. Pola "periksa, lalu lanjutkan" ini memastikan loop tidak memproses data sampah. Dan ingat: read memecah berdasarkan karakter tunggal pada IFS — untuk delimiter multi-karakter (mis. ||), gunakan alat lain seperti awk -F'\|\|'.

Misteri Subshel: Mengapa Variabel "Hilang" Setelah Pipeline

Ini salah satu misteri Bash paling terkenal dan paling sering membuat admin menyerang tembok. Coba jalankan script berikut:

Variabel yang hilang setelah pipeline
total=0
cat data.txt | while read -r baris; do
    total=$((total + 1))
done
echo "Total baris: $total"   # output: Total baris: 0  <- BUG!
total tetap 0 — perubahan di pipeline tidak terlihat di luar

Kalian mengharapkan total berisi jumlah baris, tetapi outputnya 0. Mengapa? Karena setiap elemen di dalam pipeline (cat ... | while ...) berjalan di subshell — proses Bash turunan yang memiliki salinan variabel sendiri. Penugasan total=$((total + 1)) terjadi di subshell, dan ketika subshell selesai, semua perubahannya dibuang. $total di shell induk tidak pernah tersentuh.

Analoginya: kalian mengirim seorang kurir (subshell) membawa buku catatan (salinan variabel). Kurir mencatat angka, tapi buku yang dia bawa adalah fotokopi — begitu dia pergi, buku asli tetap kosong.

Ada beberapa solusi. Yang paling sederhana: jangan gunakan pipeline sama sekali — gunakan redirection langsung:

Solusi 1: redirection, bukan pipeline
total=0
while read -r baris; do
    total=$((total + 1))
done < data.txt
echo "Total baris: $total"
Loop berjalan di shell yang sama, variabel tersimpan

Solusi alternatif untuk kasus tertentu — jika kalian benar-benar butuh pipeline (misalnya karena ada proses lain yang menyaring data), pakai process substitution atau pindahkan hasil ke variabel dengan mapfile:

Solusi 2: process substitution & mapfile
total=0
while read -r baris; do
    total=$((total + 1))
done < <(grep -v '^#' data.txt)
echo "Total: $total"
 
mapfile -t baris_baris < data.txt
echo "Jumlah baris: ${#baris_baris[@]}"
Kedua cara ini mempertahankan perubahan variabel

Warning

Prinsip yang harus diingat: setiap perintah di dalam pipeline a | b | c berjalan di subshell, dan semua variabel yang diubah di dalamnya tidak akan terlihat setelah pipeline selesai. Ini berlaku tidak hanya untuk while — berlaku juga untuk perulangan lain yang dihubungkan ke pipeline. Kalau sebuah variabel "tidak mau berubah" di script kalian, curigai pipeline sebagai penyebabnya terlebih dahulu. Aturan praktis: gunakan done < file (redirection) atau while ... done < <(command) (process substitution), bukan pipeline.

Kesalahan Umum dalam while, until, dan Membaca File

KesalahanGejalaSolusi
Lupa memperbarui kondisi di dalam loopInfinite loopPastikan ada perintah yang mengubah kondisi tiap iterasi
`while ... donecommand` (pipeline)Variabel hilang setelah loop
read line tanpa -rBackslash di data hilang/dicernaSelalu read -r line
Lupa done < fileLoop tidak membaca file, read menunggu stdinTempel redirection di done
while read dengan baris berspasi pembukaSpasi awal terpotongwhile IFS= read -r line
Mengetik while tanpa ; do atau do terpisahsyntax error near unexpected tokenFormat: while [ kondisi ]; do ... done

Caution

Infinite loop adalah musuh paling berbahaya di episode ini. Di terminal, Ctrl+C menghentikannya — tetapi di script yang berjalan non-interaktif (cron, CI), tidak ada tombol itu. Kebiasaan yang menyelamatkan nyawa: selalu beri batas pada loop yang melibatkan kondisi eksternal, misalnya counter maksimum percobaan: for ((attempt=0; attempt<10; attempt++)); do [ kondisi ] && break; sleep 5; done. Dan saat menguji script baru, jalankan dengan timeout 10 ./script.sh sebagai jaring pengaman.

Penutup

Pada episode 12 ini kita telah melengkapi perulangan Bash dengan while (berjalan selama kondisi benar), until (berjalan sampai kondisi benar), dan pola while true + break untuk daemon dan REPL. Yang lebih penting, kita menguasai pola paling produktif dalam scripting Bash: while IFS= read -r line; do ...; done < file untuk membaca file baris demi baris, memecah CSV menjadi field dengan IFS=',', dan mengungkap misteri subshell — mengapa variabel yang diubah dalam pipeline "menghilang" dan bagaimana menghindarinya.

Prinsip yang harus kalian bawa pulang: for untuk daftar yang diketahui, while/until untuk kondisi yang dievaluasi, dan selalu read -r (plus IFS= bila perlu) saat menyentuh data dari file. Dengan kombinasi pengkondisian dan perulangan, script kalian kini bisa membaca, menilai, dan mengulang — tiga kemampuan inti automation.

Namun ada satu masalah yang mulai terasa: kode kalian semakin panjang, dan pola-pola yang sama (misalnya "baca file, filter, laporkan") mulai terulang di banyak tempat. Di episode 13 selanjutnya kita akan membahas solusinya: functions — cara membungkus logika menjadi blok yang bisa dipanggil ulang, lengkap dengan local variable, argumen, dan nilai balik. Di sanalah script kalian berubah dari sekadar menjalankan tugas menjadi arsitektur kode yang rapi. Sampai jumpa di episode berikutnya!

Belajar BASH Scripting - Perulangan Bagian 2: while, until & Membaca File | Belajar BASH Scripting