Skrip Bash pertama: variabel, kondisi, perulangan, dan status keluar

Skrip shell menyimpan perintah dan alur kendali dalam program yang dapat dijalankan berulang kali. Untuk memulai di Bash, lindungi ekspansi variabel dengan tanda kutip, validasi masukan, dan periksa status keluar sambil membuat serta menguji skrip kecil.

Pelajaran ini membuat program pertama yang disimpan dalam berkas. Tinjau alur eksekusi shell, variabel, dan operator untuk dasarnya, serta panduan galat Bash dan operasi berkas yang aman berbahasa Inggris untuk batasan kegagalan, jalur, dan eksekusi bersamaan.

Memilih Bash dan menyiapkan direktori kerja

Latihan ditujukan untuk Bash pada Ubuntu dan Rocky Linux. Fitur seperti [[ ... ]] dan array tidak tersedia pada setiap shell sh; jangan menjalankan skrip Bash dengan sh script.sh. Periksa bash --version, gunakan direktori baru, dan simpan berkas dengan akhir baris LF, bukan CRLF. Jalankan blok latihan dalam sesi Bash yang sama agar variabel dan direktori kerja tetap sesuai.

lab=$(mktemp -d "$HOME/linux-script-lab.XXXXXX") &&
cd "$lab" &&
mkdir "sample files" &&
printf "one\n" > "sample files/alpha.txt" &&
printf "two\n" > "sample files/beta.txt"

Rangkaian && menghentikan langkah berikutnya jika pembuatan direktori sementara, perpindahan direktori, atau penulisan sebelumnya gagal. Pastikan setiap tahap berhasil sebelum melanjutkan. Direktori sample files sengaja mengandung spasi untuk menguji penanganan jalur.

Membuat skrip lengkap yang dapat dijalankan

Blok berikut membuat list-files.sh di direktori kerja saat ini. Program memvalidasi satu argumen direktori dan menampilkan nama berkas biasa di dalamnya. Program yang dihasilkan tidak mengubah berkas yang didaftar; tahap persiapan dan pembuatan program tetap menulis berkas latihan baru.

cat > list-files.sh <<'EOF'
#!/usr/bin/env bash
if (( $# != 1 )); then
  printf "Usage: %s DIRECTORY\n" "$0" >&2
  exit 2
fi
directory=$1
if [[ ! -d "$directory" ]]; then
  printf "Not a directory: %s\n" "$directory" >&2
  exit 1
fi
count=0
for path in "$directory"/*; do
  [[ -f "$path" ]] || continue
  printf "%s\n" "${path##*/}"
  count=$((count + 1))
done
printf "files=%s\n" "$count"
EOF
bash -n list-files.sh
bash list-files.sh "sample files"

Keluaran yang diharapkan adalah alpha.txt, beta.txt, dan files=2; urutan nama dapat dipengaruhi locale, yaitu pengaturan bahasa dan pengurutan lingkungan. bash -n memeriksa sintaks saja, bukan jalur atau izin saat berjalan. Baris awal #! adalah shebang yang memilih interpreter, bukan prompt terminal.

Penutup here-document EOF harus berada pada baris tersendiri tanpa spasi tambahan. Penulisan <<'EOF' mencegah ekspansi isi saat berkas dibuat, sehingga $1 dan variabel lain tetap tersimpan untuk dievaluasi ketika skrip dijalankan. Jika pemeriksaan sintaks gagal, perbaiki berkas sebelum menjalankannya.

Memahami variabel dan tanda kutip

Penugasan variabel memakai tanda sama dengan tanpa spasi: directory=$1. Saat memakai nilainya, "$directory" mengirim jalur yang mengandung spasi sebagai satu argumen. Kutip tunggal biasanya mencegah ekspansi, sedangkan kutip ganda mengizinkan ekspansi parameter Bash sambil mencegah pemisahan kata dan ekspansi nama berkas. Tidak diperlukan eval untuk menafsirkan ulang masukan sebagai perintah.

Pada "$directory"/*, bagian direktori dilindungi sementara tanda bintang tetap melakukan ekspansi nama berkas. Dengan pengaturan Bash bawaan, pola tanpa kecocokan dapat dibiarkan sebagai teks; pemeriksaan [[ -f "$path" ]] || continue melewatinya. Pola ini tidak memasukkan dotfile, yaitu nama yang diawali titik, dan tidak menelusuri subdirektori secara rekursif. Tautan simbolis yang menunjuk berkas biasa dapat memenuhi pemeriksaan -f.

Membaca argumen, kondisi, perulangan, dan status

Sintaks Makna
$# / $1 Jumlah argumen / argumen pertama
[[ -d ... ]] Memeriksa apakah target merupakan direktori
for ...; do ...; done Menjalankan isi perulangan untuk setiap hasil ekspansi
${path##*/} Menghapus awalan hingga garis miring terakhir untuk mengambil nama berkas
exit 0 / 1 / 2 Berhasil / target tidak valid / kesalahan penggunaan dalam contoh ini

Jika printf terakhir berhasil, skrip berakhir dengan status 0. Makna khusus 1 dan 2 ditentukan oleh skrip ini, bukan klasifikasi universal untuk semua perintah. $? berisi status perintah yang baru saja selesai, jadi periksa sebelum menjalankan perintah lain.

bash list-files.sh
printf "exit=%s\n" "$?"
bash list-files.sh missing-directory
printf "exit=%s\n" "$?"
chmod u+x list-files.sh
./list-files.sh "sample files"

Pemanggilan tanpa argumen seharusnya menampilkan petunjuk penggunaan pada stderr dan exit=2. Jalur yang tidak ada menghasilkan pesan target tidak valid dan exit=1. Setelah chmod u+x, pemanggilan langsung pada direktori contoh seharusnya kembali menampilkan dua nama dan files=2.

Mengubah satu kondisi dan membandingkan hasilnya

  1. Jalankan program pada direktori contoh semula dan pastikan jumlahnya 2.
  2. Tambahkan gamma.txt di dalam sample files, lalu jalankan lagi; jumlahnya seharusnya menjadi 3.
  3. Hapus hanya berkas yang baru ditambahkan dan pastikan jumlah kembali menjadi 2.
  4. Uji direktori kosong untuk memperoleh files=0, lalu jalur yang tidak ada untuk memperoleh galat dan status 1.

Jika setelah menyunting di Windows muncul pesan tentang bash\r atau ^M, periksa akhir baris. bash FILE membaca skrip secara langsung; ./FILE memerlukan izin eksekusi dan baris interpreter yang valid pada Linux. Periksa direktori kerja sebelum membersihkan data latihan.

Jika editor Windows menunjukkan CRLF, ubah menjadi LF dan simpan. Di VS Code, pilih indikator CRLF pada bilah status lalu pilih LF. Dengan GNU sed, rangkaian berikut membuat salinan cadangan sebelum mengubah list-files.sh latihan. Jika list-files.sh.crlf-backup sudah ada, periksa dan simpan salinan itu terlebih dahulu atau pilih nama cadangan lain serta sesuaikan perintah; jangan menimpa satu-satunya salinan yang hendak dipertahankan.

cp -i -- list-files.sh list-files.sh.crlf-backup &&
sed -i 's/\r$//' list-files.sh &&
bash -n list-files.sh &&
bash list-files.sh "sample files"

Pemeriksaan sintaks seharusnya berakhir dengan status 0 tanpa keluaran. Dengan dua berkas contoh semula, hasil program seharusnya files=2. Untuk membatalkan konversi, periksa isi cadangan lalu pulihkan dengan cp -i -- list-files.sh.crlf-backup list-files.sh. Konfirmasi penimpaan hanya setelah memastikan sumber dan tujuannya benar; jika cadangan memakai CRLF, pemulihan juga mengembalikan akhir baris tersebut.

Dokumentasi resmi