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.
$0
- Nama script$1
hingga$9
- Argumen untuk script.$1
adalah argumen pertama dan seterusnya.$@
- Semua argumen$#
- Jumlah argumen$?
- Kode pengembalian perintah sebelumnya$$
- Nomor identifikasi proses (PID) untuk script saat ini!!
- Seluruh perintah terakhir, termasuk argumen. Pola umum adalah untuk menjalankan perintah hanya agar gagal karena kurangnya izin; Kita dapat dengan cepat menjalankan kembali perintah dengan sudo dengan melakukansudo !!
$_
- Argumen terakhir dari perintah terakhir. Jika Kita berada dalam shell interaktif, Kita juga dapat dengan cepat mendapatkan nilai ini dengan mengetikEsc
diikuti dengan.
atauAlt+.
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.
- Wildcard - Setiap kali Kita ingin melakukan semacam pencocokan wildcard, Kita dapat menggunakan
?
dan*
untuk mencocokkan satu atau sejumlah karakter berturut-turut. Misalnya, dengan filefoo
,foo1
,foo2
,foo10
danbar
, perintahrm foo?
akan menghapusfoo1
danfoo2
sedangkanrm foo*
akan menghapus semuanya kecualibar
. - Kurung kurawal
{}
- Setiap kali Kita memiliki substring umum dalam serangkaian perintah, Kita dapat menggunakan kurung kurawal agar bash memperluas ini secara otomatis. Ini sangat berguna saat memindahkan atau mengonversi file.
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:
- Fungsi harus dalam bahasa yang sama dengan shell, sedangkan script dapat ditulis dalam bahasa apa pun. Inilah mengapa menyertakan shebang untuk script itu penting.
- Fungsi dimuat sekali ketika definisinya dibaca. Script dimuat setiap kali dieksekusi. Ini membuat fungsi sedikit lebih cepat untuk dimuat, tetapi setiap kali Kita mengubahnya, Kita harus memuat ulang definisinya.
- Fungsi dijalankan dalam lingkungan shell saat ini sedangkan script dijalankan dalam prosesnya sendiri. Dengan demikian, fungsi dapat memodifikasi variabel lingkungan, mis. mengubah direktori Kita saat ini, sedangkan script tidak dapat. Script akan diteruskan oleh variabel lingkungan nilai yang telah diekspor menggunakan
export
.
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.
Navigasi Direktori
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
-
Baca
man ls
dan tulis perintahls
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 ..
-
Tulis fungsi bash
marco
danpolo
yang melakukan hal berikut. Kapan pun Kita mengeksekusimarco
, direktori kerja saat ini harus disimpan dalam beberapa cara, lalu ketika Kita mengeksekusipolo
, tidak peduli direktori apa Kita berada,polo
haruscd
Kita kembali ke direktori tempat Kita mengeksekusimarco
. Untuk kemudahan debugging, Kita dapat menulis kode dalam filemarco.sh
dan (muat ulang) definisi ke shell Kita dengan mengeksekusisource marco.sh
. -
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"
-
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 sepertitar
mengambil input dari argumen. Untuk menjembatani perbedaan ini, ada perintahxargs
yang akan mengeksekusi perintah menggunakan STDIN sebagai argumen. Misalnyals | 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
untukxargs
).Jika Kita menggunakan macOS, perhatikan bahwa
find
BSD defaultnya berbeda dari yang disertakan dalam GNU coreutils. Kita dapat menggunakan-print0
padafind
dan flag-0
padaxargs
. 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 menggunakanbrew
. -
(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:
-
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!
-
Bermain “Petak Umpet” di seluruh rumah, di mana Kita selalu dapat kembali ke “markas” tidak peduli seberapa jauh Kita berjalan.
-
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!
-
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.
-
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!