Skip to content

Scripting dengan Cangkang - seri Missing Semester

Published: at 09.56

Dalam artikel sebelumnya, kita telah mempelajari dasar-dasar penggunaan shell, seperti menjalankan perintah dan menggunakan pipa untuk menghubungkan perintah. Namun, dalam banyak skenario, kita ingin melakukan serangkaian perintah dan menggunakan ekspresi aliran kontrol (“Flow Control”) seperti pernyataan kondisional atau perulangan.

Shell Scripting

Shell scripting adalah langkah selanjutnya dalam kompleksitas. Sebagian besar shell memiliki bahasa scripting mereka sendiri dengan variabel, aliran kontrol, dan sintaksnya sendiri. Yang membedakan shell scripting dari bahasa pemrograman scripting lainnya adalah bahwa ia dioptimalkan untuk melakukan tugas-tugas yang berhubungan dengan shell. Jadi, membuat pipa perintah, menyimpan hasil ke dalam file, dan membaca dari input stKitar adalah primitif dalam shell scripting, yang membuatnya lebih mudah digunakan daripada bahasa scripting tujuan umum. Untuk bagian ini, kita akan fokus pada bash scripting karena itu yang paling umum.

Analoginya, shell scripting seperti membuat resep masakan. Setiap langkah dalam resep adalah perintah yang harus dijalankan, dan variabel seperti takaran bahan yang dapat diubah sesuai kebutuhan. Aliran kontrol seperti “jika telur habis, gunakan buttermilk” adalah pernyataan kondisional. Dengan menggabungkan perintah, variabel, dan aliran kontrol, Kita dapat membuat script untuk mengotomatiskan tugas-tugas yang kompleks.

Untuk menetapkan variabel dalam bash, gunakan sintaksis foo=bar dan akses nilai variabel dengan $foo. Perhatikan bahwa foo = bar tidak akan berfungsi karena itu diartikan sebagai memanggil program foo dengan argumen = dan bar. Secara umum, dalam shell script karakter spasi akan melakukan pemisahan argumen. Perilaku ini bisa membingungkan pada awalnya, jadi selalu periksa itu.

String dalam bash dapat ditentukan dengan pembatas ' dan ", tetapi keduanya tidak setara. String yang dibatasi dengan ' adalah string literal dan tidak akan mensubstitusi nilai variabel, sedangkan string yang dibatasi dengan " akan melakukannya.

foo=bar
echo "$foo"
# mencetak bar
echo '$foo'
# mencetak $foo

Sama seperti kebanyakan bahasa pemrograman, bash mendukung teknik aliran kontrol termasuk if, case, while, dan for. Demikian pula, bash memiliki fungsi yang mengambil argumen dan dapat beroperasi dengannya. Berikut adalah contoh fungsi yang membuat direktori dan masuk ke dalamnya.

mcd () {
    mkdir -p "$1"
    cd "$1"
}

Di sini $1 adalah argumen pertama untuk script/fungsi. Tidak seperti bahasa scripting lainnya, bash menggunakan berbagai variabel khusus untuk merujuk argumen, kode kesalahan, dan variabel relevan lainnya. Di bawah ini adalah daftar beberapa di antaranya. Daftar yang lebih lengkap dapat ditemukan di sini.

Perintah sering kali akan mengembalikan output menggunakan STDOUT, kesalahan melalui STDERR, dan Kode Pengembalian untuk melaporkan kesalahan dengan cara yang lebih ramah script. Kode pengembalian atau status keluar adalah cara script/perintah untuk berkomunikasi bagaimana eksekusi berjalan. Nilai 0 biasanya berarti semuanya berjalan dengan baik; apa pun yang berbeda dari 0 berarti terjadi kesalahan.

Kode keluar dapat digunakan untuk menjalankan perintah secara bersyarat menggunakan && (operator and) dan || (operator or), keduanya adalah operator short-circuiting. Perintah juga dapat dipisahkan dalam baris yang sama menggunakan titik koma ;. Program true akan selalu memiliki kode pengembalian 0 dan perintah false akan selalu memiliki kode pengembalian 1. Mari kita lihat beberapa contoh:

false || echo "Oops, gagal"
# Oops, gagal

true || echo "Tidak akan dicetak"
#

true && echo "Semua berjalan dengan baik"
# Semua berjalan dengan baik

false && echo "Tidak akan dicetak"
#

true ; echo "Ini akan selalu berjalan"
# Ini akan selalu berjalan

false ; echo "Ini akan selalu berjalan"
# Ini akan selalu berjalan

Analoginya seperti menggunakan pernyataan “dan” dan “atau” dalam bahasa sehari-hari. Jika Kita mengatakan “pergi ke toko dan beli susu”, Kita hanya akan membeli susu jika Kita pergi ke toko terlebih dahulu (keduanya harus benar). Di sisi lain, jika Kita mengatakan “menangkan lotre atau pergi bekerja”, Kita hanya akan pergi bekerja jika Kita tidak memenangkan lotre (setidaknya satu harus benar). Operator ; seperti mengatakan “lakukan ini; kemudian lakukan itu” tanpa memperhatikan hasil dari perintah pertama.

Pola umum lainnya adalah ingin mendapatkan output dari suatu perintah sebagai variabel. Ini dapat dilakukan dengan substitusi perintah. Setiap kali Kita menempatkan $( CMD ), itu akan menjalankan CMD, mendapatkan output dari perintah dan menggantikannya di tempat. Misalnya, jika Kita melakukan for file in $(ls), shell akan terlebih dahulu memanggil ls dan kemudian melakukan iterasi atas nilai-nilai tersebut. Fitur serupa yang kurang dikenal adalah substitusi proses, <( CMD ) akan menjalankan CMD dan menempatkan output dalam file sementara dan mengganti <() dengan nama file tersebut. Ini berguna ketika perintah mengharapkan nilai dilewatkan melalui file alih-alih melalui STDIN. Misalnya, diff <(ls foo) <(ls bar) akan menunjukkan perbedaan antara file dalam direktori foo dan bar.

Karena itu adalah informasi yang sangat banyak, mari kita lihat contoh yang menunjukkan beberapa fitur ini. Ini akan mengiterasi melalui argumen yang kita berikan, mencari string foobar, dan menambahkannya ke file sebagai komentar jika tidak ditemukan.

#!/bin/bash

echo "Program dimulai pada $(date)" # Tanggal akan disubstitusi

echo "Menjalankan program $0 dengan $# argumen dengan pid $$"

for file in "$@"; do
    grep foobar "$file" > /dev/null 2> /dev/null
    # Ketika pola tidak ditemukan, grep memiliki status keluar 1
    # Kita mengarahkan STDOUT dan STDERR ke register null karena kita tidak peduli dengan hasilnya
    if [[ $? -ne 0 ]]; then
        echo "File $file tidak memiliki foobar, menambahkannya"
        echo "# foobar" >> "$file"
    fi
done

Dalam perbandingan, kita menguji apakah $? tidak sama dengan 0. Bash mengimplementasikan banyak perbandingan semacam ini - Kita dapat menemukan daftar terperinci di halaman manual untuk test. Saat melakukan perbandingan dalam bash, cobalah untuk menggunakan tKita kurung gKita [[ ]] daripada tKita kurung tunggal [ ]. Kemungkinan membuat kesalahan lebih rendah meskipun itu tidak akan portabel ke sh. Penjelasan lebih rinci dapat ditemukan di sini.

Analogi untuk perbandingan ini seperti memeriksa hasil tugas. Jika hasil tugas tidak sama dengan yang diharapkan (dalam hal ini, 0 berarti tidak ada kesalahan), maka kita perlu mengambil tindakan lebih lanjut (menambahkan komentar foobar ke file).

Saat meluncurkan script, Kita sering kali ingin memberikan argumen yang mirip. Bash memiliki cara untuk mempermudah ini, memperluas ekspresi dengan melakukan ekspansi nama file. Teknik ini sering disebut sebagai shell globbing.

convert image.{png,jpg}
# Akan diperluas menjadi
convert image.png image.jpg

cp /path/to/project/{foo,bar,baz}.sh /newpath
# Akan diperluas menjadi
cp /path/to/project/foo.sh /path/to/project/bar.sh /path/to/project/baz.sh /newpath

# Teknik globbing juga dapat digabungkan
mv *{.py,.sh} folder
# Akan memindahkan semua file *.py dan *.sh


mkdir foo bar
# Ini membuat file foo/a, foo/b, ... foo/h, bar/a, bar/b, ... bar/h
touch {foo,bar}/{a..h}
touch foo/x bar/y
# Menunjukkan perbedaan antara file dalam foo dan bar
diff <(ls foo) <(ls bar)
# Menghasilkan
# < x
# ---
# > y

Analogi untuk wildcard adalah seperti mengatakan “ambilkan saya semua buku yang judulnya dimulai dengan ‘Harry Potter’”, alih-alih menyebutkan setiap judul buku secara individual. Ini memungkinkan Kita untuk merujuk banyak file atau direktori dengan pola umum.

Menulis script bash bisa menjadi rumit dan tidak intuitif. Ada alat seperti shellcheck yang akan membantu Kita menemukan kesalahan dalam script sh/bash Kita.

Perhatikan bahwa script tidak harus ditulis dalam bash untuk dipanggil dari terminal. Misalnya, berikut adalah script Python sederhana yang mengeluarkan argumennya dalam urutan terbalik:

#!/usr/local/bin/python
import sys
for arg in reversed(sys.argv[1:]):
    print(arg)

Kernel tahu untuk menjalankan script ini dengan interpreter python alih-alih perintah shell karena kita menyertakan baris shebang di bagian atas script. Merupakan praktik yang baik untuk menulis baris shebang menggunakan perintah env yang akan diselesaikan ke mana pun perintah hidup dalam sistem, meningkatkan portabilitas script Kita. Untuk menyelesaikan lokasi, env akan menggunakan variabel lingkungan PATH yang kita perkenalkan dalam kuliah pertama. Untuk contoh ini baris shebang akan terlihat seperti #!/usr/bin/env python.

Beberapa perbedaan antara fungsi shell dan script yang perlu Kita ingat adalah:

Seperti halnya bahasa pemrograman apa pun, fungsi adalah konstruksi yang kuat untuk mencapai modularitas, penggunaan kembali kode, dan kejelasan kode shell. Seringkali script shell akan menyertakan definisi fungsinya sendiri.

Analogi untuk perbedaan antara fungsi dan script adalah seperti perbedaan antara menyiapkan hidangan dari awal di dapur Kita sendiri (fungsi) versus memesan makanan dari restoran (script). Menyiapkan hidangan sendiri memungkinkan Kita untuk mengubah resep dan menyesuaikan bahan sesuai keinginan, tetapi membutuhkan lebih banyak waktu dan upaya. Memesan dari restoran lebih cepat dan mudah, tetapi Kita memiliki lebih sedikit kontrol atas hasil akhirnya dan harus “membuat pesanan baru” (menjalankan script lagi) setiap kali Kita menginginkannya.

Peralatan Shell

Mencari cara menggunakan perintah

Pada titik ini, Kita mungkin bertanya-tanya bagaimana menemukan flag untuk perintah dalam bagian aliasing seperti ls -l, mv -i, dan mkdir -p. Lebih umum lagi, dengan perintah tertentu, bagaimana Kita mencari tahu apa yang dilakukannya dan opsi-opsi berbedanya? Kita selalu dapat mulai mencari di Google, tetapi karena UNIX lebih dulu ada sebelum StackOverflow, ada cara bawaan untuk mendapatkan informasi ini.

Seperti yang kita lihat dalam kuliah shell, pendekatan tingkat pertama adalah memanggil perintah tersebut dengan flag -h atau --help. Pendekatan yang lebih rinci adalah menggunakan perintah man. Singkatan dari manual, man menyediakan halaman manual (disebut manpage) untuk perintah yang Kita tentukan. Misalnya, man rm akan menampilkan perilaku perintah rm beserta flag yang diambilnya, termasuk flag -i yang kami tunjukkan sebelumnya. Bahkan perintah non-native yang Kita instal akan memiliki entri manpage jika pengembang menuliskannya dan menyertakannya sebagai bagian dari proses instalasi. Untuk alat interaktif seperti yang berbasis ncurses, bantuan untuk perintah sering kali dapat diakses dalam program menggunakan perintah :help atau mengetik ?.

Terkadang manpage dapat memberikan deskripsi yang terlalu rinci tentang perintah, sehingga sulit untuk menguraikan flag/sintaks mana yang digunakan untuk kasus penggunaan umum. Halaman TLDR adalah solusi pelengkap yang rapi yang berfokus pada memberikan contoh kasus penggunaan perintah sehingga Kita dapat dengan cepat mengetahui opsi mana yang akan digunakan. Misalnya, saya merasa diri saya merujuk kembali ke halaman tldr untuk tar dan ffmpeg jauh lebih sering daripada manpage.

Analogi untuk ini seperti menggunakan buku petunjuk (manpage) versus panduan ringkas (TLDR). Buku petunjuk akan memberi Kita setiap detail tentang cara mengoperasikan sesuatu, tetapi dapat membingungkan dan sulit dipahami. Panduan ringkas memberikan instruksi langsung untuk tugas-tugas umum, tetapi mungkin tidak mencakup setiap situasi. Keduanya berguna dalam konteks yang berbeda.

Menemukan file

Salah satu tugas berulang paling umum yang dihadapi setiap pemrogram adalah menemukan file atau direktori. Semua sistem seperti UNIX dilengkapi dengan find, alat shell hebat untuk menemukan file. find akan secara rekursif mencari file yang cocok dengan beberapa kriteria. Beberapa contoh:

# Temukan semua direktori bernama src
find . -name src -type d
# Temukan semua file python yang memiliki folder bernama test di jalurnya
find . -path '*/test/*.py' -type f
# Temukan semua file yang dimodifikasi dalam satu hari terakhir
find . -mtime -1
# Temukan semua file zip dengan ukuran dalam kisaran 500k hingga 10M
find . -size +500k -size -10M -name '*.tar.gz'

Selain mencantumkan file, find juga dapat melakukan tindakan atas file yang cocok dengan query Kita. Properti ini dapat sangat membantu untuk menyederhanakan tugas yang cukup monoton.

# Hapus semua file dengan ekstensi .tmp
find . -name '*.tmp' -exec rm {} \;
# Temukan semua file PNG dan konversi menjadi JPG
find . -name '*.png' -exec convert {} {}.jpg \;

Meskipun find ada di mana-mana, sintaksnya terkadang bisa sulit diingat. Misalnya, untuk menemukan file yang sesuai dengan beberapa pola PATTERN saja, Kita harus menjalankan find -name '*PATTERN*' (atau -iname jika Kita ingin pencocokan polanya tidak sensitif huruf besar-kecil). Kita dapat mulai membangun alias untuk skenario tersebut, tetapi bagian dari filosofi shell adalah baik untuk ngulik alternatif. Ingat, salah satu properti terbaik dari shell adalah Kita hanya memanggil program, jadi Kita dapat menemukan (atau bahkan menulis sendiri) pengganti untuk beberapa. Misalnya, fd adalah alternatif find yang sederhana, cepat, dan ramah pengguna. Ini menawarkan beberapa default yang bagus seperti output berwarna, pencocokan regex default, dan dukungan Unicode. Ini juga memiliki, menurut pendapat saya, sintaks yang lebih intuitif. Misalnya, sintaks untuk menemukan pola PATTERN adalah fd PATTERN.

Sebagian besar akan setuju bahwa find dan fd itu bagus, tetapi beberapa dari Kita mungkin bertanya-tanya tentang efisiensi mencari file setiap kali versus mengompilasi semacam indeks atau basis data untuk pencarian cepat. Itulah gunanya locate. locate menggunakan basis data yang diperbarui menggunakan updatedb. Dalam kebanyakan sistem, updatedb diperbarui setiap hari melalui cron. Oleh karena itu, satu kompensasi antara keduanya adalah kecepatan vs kesegaran. Selain itu, find dan alat serupa juga dapat menemukan file menggunakan atribut seperti ukuran file, waktu modifikasi, atau izin file, sedangkan locate hanya menggunakan nama file. Perbandingan lebih mendalam dapat ditemukan di sini.

Analogi untuk ini seperti mencari buku di perpustakaan. find seperti berjalan melalui setiap rak dan memeriksa setiap buku secara individual, yang memakan waktu tetapi menyeluruh dan memungkinkan Kita mencari berdasarkan banyak atribut seperti subjek, penulis, dll. Di sisi lain, locate seperti menggunakan katalog kartu perpustakaan - jauh lebih cepat, tetapi hanya berfungsi jika buku yang Kita cari sudah ada dalam katalog dan Kita hanya dapat mencari berdasarkan judul.

Menemukan kode

Menemukan file berdasarkan nama itu berguna, tetapi cukup sering Kita ingin mencari berdasarkan isi file. Skenario umum adalah ingin mencari semua file yang berisi beberapa pola, beserta di mana dalam file tersebut pola tersebut terjadi. Untuk mencapai ini, sebagian besar sistem seperti UNIX menyediakan grep, alat generik untuk mencocokkan pola dari input teks. grep adalah alat shell yang sangat berharga yang akan kita bahas lebih rinci selama kuliah tentang pengelolaan data.

Untuk saat ini, ketahui bahwa grep memiliki banyak flag yang membuatnya menjadi alat yang sangat serbaguna. Beberapa yang sering saya gunakan adalah -C untuk mendapatkan Konteks di sekitar baris yang cocok dan -v untuk membalikkan pencocokan, yaitu mencetak semua baris yang tidak cocok dengan pola. Misalnya, grep -C 5 akan mencetak 5 baris sebelum dan sesudah kecocokan. Ketika ingin mencari dengan cepat melalui banyak file, Kita ingin menggunakan -R karena akan secara Rekursif masuk ke direktori dan mencari file untuk string yang cocok.

Tetapi grep -R dapat ditingkatkan dalam banyak hal, seperti mengabaikan folder .git, menggunakan dukungan multi CPU, &c. Banyak alternatif grep telah dikembangkan, termasuk ack, ag, dan rg. Semuanya fantastis dan hampir menyediakan fungsionalitas yang sama. Untuk saat ini saya tetap menggunakan ripgrep (rg), mengingat seberapa cepat dan intuitifnya. Beberapa contoh:

# Temukan semua file python di mana saya menggunakan library requests
rg -t py 'import requests'
# Temukan semua file (termasuk file tersembunyi) tanpa baris shebang
rg -u --files-without-match "^#\!"
# Temukan semua kecocokan foo dan cetak 5 baris berikutnya
rg foo -A 5
# Cetak statistik kecocokan (jumlah baris dan file yang cocok)
rg --stats PATTERN

Perhatikan bahwa seperti halnya find/fd, penting bagi Kita untuk mengetahui bahwa masalah ini dapat dengan cepat diselesaikan menggunakan salah satu alat ini, sementara alat spesifik yang Kita gunakan tidak terlalu penting.

Analogi untuk ini seperti menggunakan pencarian kata dalam dokumen. grep seperti menggunakan “temukan” di pengolah kata - Kita dapat dengan cepat menemukan semua kemunculan kata atau frasa tertentu. Alat seperti ack, ag atau rg seperti menggunakan pencarian kata tingkat lanjut, yang memungkinkan Kita untuk menyaring hasil berdasarkan jenis file, mengecualikan direktori tertentu, dll. Apa yang penting adalah mengetahui kemampuan pencarian sehingga Kita dapat dengan cepat menemukan apa yang Kita butuhkan, sementara pengolah kata khusus yang Kita gunakan adalah masalah preferensi.

Menemukan perintah shell

Sejauh ini kita telah melihat cara menemukan file dan kode, tetapi karena Kita mulai menghabiskan lebih banyak waktu di shell, Kita mungkin ingin menemukan perintah spesifik yang Kita ketik pada suatu waktu. Hal pertama yang perlu diketahui adalah mengetik panah atas akan memberi Kita kembali perintah terakhir Kita, dan jika Kita terus menekannya, Kita akan perlahan-lahan melewati riwayat shell Kita.

Perintah history akan memungkinkan Kita mengakses riwayat shell Kita secara terprogram. Ini akan mencetak riwayat shell Kita ke output stKitar. Jika kita ingin mencari di sana, kita dapat menyalurkan output itu ke grep dan mencari pola. history | grep find akan mencetak perintah yang berisi substring “find”.

Dalam kebanyakan shell, Kita dapat memanfaatkan Ctrl+R untuk melakukan pencarian mundur melalui riwayat Kita. Setelah menekan Ctrl+R, Kita dapat mengetik substring yang ingin Kita cocokkan untuk perintah dalam riwayat Kita. Saat Kita terus menekannya, Kita akan bersiklus melalui kecocokan dalam riwayat Kita. Ini juga dapat diaktifkan dengan panah ATAS/BAWAH di zsh. Sebuah tambahan bagus di atas Ctrl+R datang dengan menggunakan binding fzf. fzf adalah penemu fuzzy serbaguna yang dapat digunakan dengan banyak perintah. Di sini digunakan untuk mencocokkan secara fuzzy melalui riwayat Kita dan menyajikan hasil dengan cara yang nyaman dan menyenangkan secara visual.

Trik terkait riwayat lain yang sangat saya nikmati adalah saran otomatis berbasis riwayat. Pertama kali diperkenalkan oleh shell fish, fitur ini secara dinamis menyelesaikan otomatis perintah shell Kita saat ini dengan perintah terakhir yang Kita ketik yang memiliki awalan umum dengannya. Ini dapat diaktifkan di zsh dan merupakan trik kualitas hidup yang bagus untuk shell Kita.

Kita dapat memodifikasi perilaku riwayat shell Kita, seperti mencegah perintah dengan spasi di awal agar tidak disertakan. Ini berguna ketika Kita mengetik perintah dengan kata sandi atau bit informasi sensitif lainnya. Untuk melakukan ini, tambahkan HISTCONTROL=ignorespace ke .bashrc Kita atau setopt HIST_IGNORE_SPACE ke .zshrc Kita. Jika Kita melakukan kesalahan dengan tidak menambahkan spasi di awal, Kita selalu dapat menghapus entri secara manual dengan mengedit .bash_history atau .zsh_history Kita.

Analogi untuk ini seperti mengingat resep yang pernah Kita buat sebelumnya. Mengetik panah atas seperti mencoba mengingatnya dalam pikiran Kita. history seperti merujuk buku resep di mana Kita mencatat setiap kali Kita memasak sesuatu, dan grep adalah seperti membuka indeks dan mencari resep tertentu. Ctrl+R seperti meminta teman menyarankan resep berdasarkan bahan-bahan atau teknik yang Kita sebutkan. Dan saran otomatis berbasis riwayat seperti ketika teman atau anggota keluarga mengingatkan Kita tentang masakan yang mirip dengan yang ingin Kita buat.

Sejauh ini, kita telah berasumsi bahwa Kita sudah berada di tempat yang Kita butuhkan untuk melakukan tindakan ini. Tapi bagaimana Kita dengan cepat menavigasi direktori? Ada banyak cara sederhana yang dapat Kita lakukan, seperti menulis alias shell atau membuat symlink dengan ln -s, tetapi yang sebenarnya adalah pengembang telah menemukan solusi yang cukup cerdas dan canggih sekarang.

Seperti tema kursus ini, Kita sering kali ingin mengoptimalkan untuk kasus umum. Menemukan file dan direktori yang sering dan/atau baru-baru ini dapat dilakukan melalui alat seperti fasd dan autojump. Fasd mengurutkan file dan direktori berdasarkan frecency, yaitu berdasarkan frekuensi dan kebaruan. Secara default, fasd menambahkan perintah z yang dapat Kita gunakan untuk cd dengan cepat menggunakan substring dari direktori yang sering dikunjungi. Misalnya, jika Kita sering pergi ke /home/user/files/cool_project Kita dapat menggunakan z cool untuk melompat ke sana. Menggunakan autojump, perubahan direktori yang sama dapat dicapai menggunakan j cool.

Alat yang lebih kompleks ada untuk dengan cepat mendapatkan gambaran umum struktur direktori: tree, broot, atau bahkan manajer file penuh seperti nnn atau ranger.

Analogi untuk ini seperti menavigasi gedung yang sangat besar. Alat seperti fasd dan autojump seperti memiliki lift ekspres pribadi yang membawa Kita langsung ke tempat-tempat yang sering Kita kunjungi berdasarkan seberapa sering dan baru-baru ini Kita mengunjunginya. tree dan broot seperti memiliki peta seluruh gedung, memungkinkan Kita melihat tata letak secara sekilas. Dan manajer file seperti nnn atau ranger seperti memiliki asisten pribadi yang dapat memandu Kita ke mana saja yang Kita butuhkan untuk pergi dan membantu Kita mengatur sepanjang jalan.

Latihan

  1. Baca man ls dan tulis perintah ls yang mencantumkan file dengan cara berikut

    • Termasuk semua file, termasuk file tersembunyi
    • Ukuran dicantumkan dalam format yang mudah dibaca manusia (mis. 454M alih-alih 454279954)
    • File diurutkan berdasarkan waktu modifikasi
    • Output berwarna

    Contoh outputnya akan terlihat seperti ini

     -rw-r--r--   1 user group 1.1M Jan 14 09:53 baz
     drwxr-xr-x   5 user group  160 Jan 14 09:53 .
     -rw-r--r--   1 user group  514 Jan 14 06:42 bar
     -rw-r--r--   1 user group 106M Jan 13 12:12 foo
     drwx------+ 47 user group 1.5K Jan 12 18:08 ..
    
  2. Tulis fungsi bash marco dan polo yang melakukan hal berikut. Kapan pun Kita mengeksekusi marco, direktori kerja saat ini harus disimpan dalam beberapa cara, lalu ketika Kita mengeksekusi polo, tidak peduli direktori apa Kita berada, polo harus cd Kita kembali ke direktori tempat Kita mengeksekusi marco. Untuk kemudahan debugging, Kita dapat menulis kode dalam file marco.sh dan (muat ulang) definisi ke shell Kita dengan mengeksekusi source marco.sh.

  3. Katakanlah Kita memiliki perintah yang gagal jarang. Untuk men-debug-nya, Kita perlu menangkap outputnya, tetapi dapat memakan waktu untuk mendapatkan run yang gagal. Tulis skrip bash yang menjalankan skrip berikut sampai gagal dan menangkap output stKitar dan stream error-nya ke file dan mencetak semuanya pada akhirnya. Bonus poin jika Kita juga dapat melaporkan berapa banyak run yang diperlukan agar skrip gagal.

    #!/usr/bin/env bash
    
    n=$(( RANDOM % 100 ))
    
    if [[ n -eq 42 ]]; then
       echo "Something went wrong"
       >&2 echo "The error was using magic numbers"
       exit 1
    fi
    
    echo "Everything went according to plan"
    
  4. Seperti yang kami bahas dalam kuliah, find’s -exec dapat sangat berguna untuk melakukan operasi atas file yang kami cari. Namun, bagaimana jika kita ingin melakukan sesuatu dengan semua file, seperti membuat file zip? Seperti yang telah Kita lihat sejauh ini, perintah akan mengambil input baik dari argumen dan STDIN. Saat menyambungkan perintah, kita menghubungkan STDOUT ke STDIN, tetapi beberapa perintah seperti tar mengambil input dari argumen. Untuk menjembatani perbedaan ini, ada perintah xargs yang akan mengeksekusi perintah menggunakan STDIN sebagai argumen. Misalnya ls | xargs rm akan menghapus file dalam direktori saat ini.

    Tugas Kita adalah menulis perintah yang secara rekursif menemukan semua file HTML dalam folder dan membuat zip dengannya. Perhatikan bahwa perintah Kita harus berfungsi bahkan jika file memiliki spasi (petunjuk: periksa flag -d untuk xargs).

    Jika Kita menggunakan macOS, perhatikan bahwa find BSD defaultnya berbeda dari yang disertakan dalam GNU coreutils. Kita dapat menggunakan -print0 pada find dan flag -0 pada xargs. Sebagai pengguna macOS, Kita harus menyadari bahwa utilitas baris perintah yang dikirimkan dengan macOS mungkin berbeda dari rekan GNU-nya; Kita dapat menginstal versi GNU jika Kita suka dengan menggunakan brew.

  5. (Lanjutan) Tulis perintah atau skrip untuk menemukan file yang terakhir dimodifikasi secara rekursif dalam suatu direktori. Lebih umum lagi, dapatkah Kita mencantumkan semua file berdasarkan waktu modifikasi terbaru?

Analogi untuk latihan ini adalah seperti:

  1. Minta asisten rumah tangga Kita untuk memberi Kita ikhtisar lemari, dengan pakaian yang telah lama tidak Kita pakai di bagian belakang, pakaian paling baru di depan, semua dalam tumpukan rapi dengan label ukuran. Bahkan kaos kaki dan pakaian dalam juga!

  2. Bermain “Petak Umpet” di seluruh rumah, di mana Kita selalu dapat kembali ke “markas” tidak peduli seberapa jauh Kita berjalan.

  3. Menyuruh asisten Kita untuk terus mencoba resep baru sampai dia berhasil membuatnya dengan sempurna, sambil mencatat setiap kesalahan sepanjang jalan. Bonus jika dia memberi tahu Kita berapa banyak upaya yang diperlukan!

  4. Meminta asisten Kita untuk menemukan semua barang dari satu kategori (mis. barang liburan) yang tersebar di seluruh rumah dan memasukkannya ke dalam satu kotak penyimpanan.

  5. Tantangan untuk asisten Kita: temukan barang yang terakhir Kita gunakan di setiap ruangan rumah. Dapatkah dia juga memberikan daftar yang diurutkan dari yang terakhir Kita gunakan hingga yang sudah lama tidak Kita sentuh?

Melalui latihan ini, Kita semakin terbiasa dengan shell dan, sama seperti memiliki alat yang tepat dalam kotak peralatan Kita, Kita mulai membangun keterampilan yang akan membantu Kita mengatasi berbagai tugas.

Kesimpulan

Dalam artikel ini, kami telah membahas dasar-dasar shell scripting dan berbagai peralatan shell yang membantu kita menemukan file, menavigasi sistem file dengan lebih efisien, dan bahkan mengotomatiskan tugas-tugas yang membosankan. Kami juga melihat beberapa analogi untuk membantu memahami konsep-konsep ini dalam konteks kehidupan nyata.

Ingatlah bahwa menguasai shell adalah proses bertahap. Semakin banyak Kita menggunakannya, semakin nyaman Kita dengannya, dan semakin banyak Kita dapat memanfaatkan kekuatannya. Jangan ragu untuk bereksperimen, mencari alat baru, dan menerapkan keterampilan ini dalam pekerjaan sehari-hari Kita.

Ke depannya, kami akan menggali lebih dalam tentang manipulasi dan pengelolaan data dalam shell. Tetap ikuti seri artikel kami untuk mempelajari lebih lanjut tentang topik yang menarik ini!

Sementara itu, teruslah berlatih dan jangan ragu untuk membagikan apa yang telah Kita pelajari dengan rekan-rekan Kita. Seperti pepatah lama, “Ajarkan seorang pria untuk memancing, dan Kita memberinya makan seumur hidup.” Dalam hal ini, ajari seseorang cara menggunakan shell, dan Kita memberdayakan mereka dalam perjalanan pemrograman mereka untuk waktu yang lama mendatang.

Semoga artikel ini bermanfaat dan menginspirasi untuk ngulik shell lebih lanjut. Sampai jumpa di artikel berikutnya!