If-Koubou

Panduan Pemula untuk Shell Scripting 2: For Loops

Panduan Pemula untuk Shell Scripting 2: For Loops (Bagaimana caranya)

Jika Anda ingin membangun kredibilitas geek Anda, bergabunglah dengan kami untuk angsuran kedua dalam seri scripting shell kami. Kami memiliki beberapa koreksi, beberapa perbaikan pada skrip minggu lalu, dan panduan tentang perulangan untuk yang belum tahu.

Naskah datecp Revisited

Dalam angsuran pertama dari panduan scripting shell kami, kami membuat skrip yang menyalin file ke direktori backup setelah menambahkan tanggal ke akhir namafile.

Samuel Dionne-Riel menunjukkan di komentar bahwa ada cara yang jauh lebih baik untuk menangani referensi variabel kami.

Argumen dipisahkan oleh ruang di shell bash, ia akan meng-tokenize ketika ada ruang di dalam perintah yang diperluas yang dihasilkan. Di skrip Anda, cp $ 1 $ 2. $ date_formatted akan berfungsi sebagaimana yang dimaksudkan selama variabel yang diperluas tidak memiliki spasi di dalamnya. Jika Anda memanggil skrip Anda dengan cara ini: datecp "nama lama saya" "nama baru saya" perluasan akan menghasilkan perintah ini: cp nama baru saya name.the_date lama saya yang sebenarnya memiliki 6 argumen.

Untuk benar mengatasi masalah ini, baris terakhir dari skrip harus: cp "$ 1" "$ 2. $ date_formatted"

Seperti yang Anda lihat, mengubah baris skrip kami dari:

cp -iv $ 1 $ 2. $ date_formatted

untuk:

cp -iv "$ 1" "$ 2". $ date_formatted

akan mengurus masalah ini saat menggunakan skrip pada file yang memiliki spasi di nama. Samuel juga menyatakan bahwa ketika menyalin dan menempelkan kode dari situs ini (atau internet pada umumnya) pastikan untuk mengganti tanda garis dan tanda kutip yang tepat untuk "tipografi yang lebih baik" yang sering menggantikannya. Kami juga akan melakukan lebih banyak untuk memastikan kode kami lebih copy / paste ramah. ;-)

Komentator lain, Myles Braithwaite, memutuskan untuk memperluas skrip kami sehingga tanggalnya akan muncul sebelum ekstensi file. Jadi, bukannya

tastyfile.mp3.07_14_11-12.34.56

kami akan mendapatkan ini:

tastyfile.07_14_11-12.34.56.mp3

yang akhirnya menjadi sedikit lebih nyaman bagi sebagian besar pengguna. Kodenya tersedia di halaman GitHub-nya. Mari kita lihat apa yang dia gunakan untuk memisahkan nama file.

date_formatted = $ (tanggal +% Y-% m-% d_% H.% M% S)
file_extension = $ (echo “$ 1” | awk -F. 'cetak $ NF')
file_name = $ (basename $ 1. $ file_extension)

cp -iv $ 1 $ file_name- $ date_formatted. $ file_extension

Saya telah sedikit mengubah formatnya, tetapi Anda dapat melihat bahwa Myles menyatakan fungsi tanggalnya di Baris 1. Di Baris 2, ia menggunakan perintah “echo” dengan argumen pertama dari skrip untuk menampilkan nama file. Dia menggunakan perintah pipa untuk mengambil output itu dan menggunakannya sebagai masukan untuk bagian selanjutnya. Setelah pipa, Myles memanggil perintah "awk", yang merupakan program pemindaian pola yang kuat. Menggunakan flag -F, dia memberi tahu perintah bahwa karakter berikutnya (setelah spasi) adalah apa yang akan mendefinisikan "pemisah lapangan". Dalam hal ini, itu adalah periode.

Sekarang, awk melihat file bernama "tastyfile.mp3" sebagai yang terdiri dari dua bidang: "tastyfile" dan "mp3". Terakhir, dia menggunakan

'cetak $ NF'

untuk menampilkan bidang terakhir. Jika file Anda memiliki beberapa periode - sehingga membuat awk melihat beberapa bidang - itu hanya akan menampilkan yang terakhir, yang merupakan ekstensi file.

Di Baris 3, ia membuat variabel baru untuk nama file dan menggunakan perintah "basename" untuk merujuk semuanya dalam $ 1 kecuali ekstensi file. Ini dilakukan dengan menggunakan basename dan memberikannya $ 1 sebagai argumennya, lalu menambahkan spasi dan ekstensi file. Ekstensi file ditambahkan secara otomatis karena variabel yang mereferensikan Baris 2. Apa yang akan dilakukan adalah mengambil

tastyfile.mp3

dan mengubahnya menjadi

tastyfile

Kemudian di baris terakhir, Myles menyusun perintah yang akan menghasilkan semuanya secara berurutan. Perhatikan bahwa tidak ada referensi ke $ 2, argumen kedua untuk skrip. Skrip khusus ini akan menyalin file tersebut ke dalam direktori Anda saat ini. Pekerjaan hebat Samuel dan Myles!

Menjalankan Skrip dan $ PATH

Kami juga menyebutkan dalam artikel Dasar kami bahwa skrip tidak diizinkan untuk direferensikan sebagai perintah secara default. Artinya, Anda harus menunjuk ke jalan skrip untuk menjalankannya:

./naskah

~ / bin / skrip

Namun, dengan menempatkan skrip Anda di ~ / bin /, Anda cukup mengetikkan nama mereka dari mana saja agar mereka dapat menjalankannya.

Para komentator menghabiskan beberapa waktu untuk memperdebatkan betapa tepatnya hal ini, karena tidak ada distro Linux modern yang menciptakan direktori itu secara default. Selain itu, tidak ada yang menambahkannya ke variabel $ PATH secara default, yaitu apa yang diperlukan agar skrip dapat dijalankan seperti perintah. Saya sedikit bingung karena setelah memeriksa variabel $ PATH saya, komentatornya benar, tetapi memanggil skrip masih berfungsi untuk saya. Saya menemukan mengapa: banyak distro Linux modern membuat file khusus di direktori home pengguna - .profile.

File ini dibaca oleh bash (kecuali .bash_profile ada di direktori home pengguna) dan di bagian bawah, ada bagian yang menambahkan folder ~ / bin / ke variabel $ PATH jika ada. Jadi, misteri itu sudah jelas. Untuk sisa seri, saya akan terus menempatkan skrip di direktori ~ / bin / karena mereka adalah skrip pengguna dan harus dapat dijalankan oleh pengguna. Dan, sepertinya kita tidak benar-benar perlu mengacaukan variabel PATH $ dengan tangan untuk membuat semuanya berjalan lancar.

Mengulangi Perintah Dengan Loops

Mari kita ke salah satu alat yang paling berguna di gudang senjata geek untuk menangani tugas yang berulang: loop. Hari ini, kita akan membahas "untuk" loop.

Garis dasar dari for-loop adalah sebagai berikut:

untuk VARIABLE dalam DAFTAR; melakukan
perintah1
perintah2

komando
selesai

VARIABEL dapat berupa variabel apa pun, meskipun paling sering huruf kecil "i" digunakan oleh konvensi. DAFTAR adalah daftar barang; Anda dapat menentukan beberapa item (memisahkan mereka dengan spasi), arahkan ke file teks eksternal, atau gunakan tanda bintang (*) untuk menunjukkan file apa pun di direktori saat ini. Perintah-perintah yang tercantum diindeks oleh konvensi, sehingga lebih mudah untuk melihat bersarang - meletakkan loop dalam loop (sehingga Anda dapat mengulang saat Anda mengulang).

Karena daftar menggunakan spasi sebagai pembatas - yaitu, spasi menandakan pindah ke item berikutnya dalam daftar - file yang memiliki spasi dalam nama tidak sangat ramah. Untuk saat ini, mari kita tetap bekerja dengan file tanpa spasi. Mari kita mulai dengan skrip sederhana untuk menampilkan nama-nama file di direktori saat ini. Buat skrip baru di folder ~ / bin / Anda yang berjudul "loopscript". Jika Anda tidak ingat cara melakukan ini (termasuk menandainya sebagai dapat dieksekusi dan menambahkan hash bang hack) lihat artikel dasar-dasar skrip bash kami.

Di dalamnya, masukkan kode berikut:

untuk saya di item1 item2 item3 item4 item5 item6; melakukan
echo “$ i”
selesai

Ketika Anda menjalankan skrip, Anda harus mendapatkan item daftar tersebut sebagai output.

Sangat sederhana, bukan? Mari kita lihat apa yang terjadi jika kita mengubah sedikit. Ubah skrip Anda jadi kata ini:

untuk saya di *; melakukan
echo “$ i”
selesai

Ketika Anda menjalankan skrip ini dalam folder, Anda harus mendapatkan daftar file yang berisi sebagai output.

Sekarang, mari kita ubah perintah echo menjadi sesuatu yang lebih berguna - katakanlah, perintah zip. Yaitu, kita akan menambahkan file ke dalam arsip. Dan, mari kita dapatkan beberapa argumen dalam campuran!

untuk saya di $ @; melakukan
arsip zip "$ i"
selesai

Ada sesuatu yang baru! “$ @” Adalah pintasan untuk “$ 1 $ 2 $ 3… $ n”. Dengan kata lain, ini adalah daftar lengkap semua argumen yang Anda tentukan. Sekarang, perhatikan apa yang terjadi ketika saya menjalankan skrip dengan beberapa file masukan.

Anda dapat melihat file mana yang ada di folder saya. Saya menjalankan perintah dengan enam argumen, dan setiap file ditambahkan ke arsip zip bernama "archive.zip". Mudah, kan?

Untuk loop sangat indah. Sekarang Anda dapat menjalankan fungsi batch pada daftar file. Misalnya, Anda dapat menyalin semua argumen skrip Anda ke dalam arsip zip, memindahkan dokumen asli ke folder yang berbeda, dan secara otomatis mengamankan salinan file zip tersebut ke komputer jarak jauh. Jika Anda mengatur file kunci dengan SSH, Anda bahkan tidak perlu memasukkan kata sandi Anda, dan Anda bahkan dapat memberi tahu script untuk menghapus file zip setelah mengunggahnya!

Menggunakan for-loops memudahkan untuk melakukan banyak tindakan untuk semua file dalam direktori. Anda dapat menumpuk berbagai macam perintah bersama-sama dan menggunakan argumen sangat mudah dibuat dan daftar on-the-fly, dan ini hanya puncak gunung es.

Bash scripters, apakah Anda punya saran? Sudahkah Anda membuat skrip yang berguna yang menggunakan loop? Ingin berbagi pemikiran Anda tentang seri ini? Tinggalkan beberapa komentar dan bantulah scripting newbies!