Why I Like cat

Bukan, posting ini bukan soal kucing, tapi soal perintah cat di UNIX (Linux/Mac/BSD). Perintah ini gunanya untuk menggabungkan (concatenate) file-file input ke standard output (bahasa sederhananya: ditampilkan ke layar). Jika hanya satu file yang diberikan sebagai input, maka file itu akan ditampilkan.

Di UNIX, kita bisa mengkomposisi banyak perintah dengan menggunakan pipe. Output perintah satu bisa dijadikan input perintah yang lain. Nah banyak orang suka menggunakan cat untuk memberikan file ke program lain, misalnya seperti ini:

cat file.txt| grep secara | wc -l

(hitung berapa jumlah baris yang mengandung kata secara)

Penggunaan perintah cat tersebut sebenarnya tidak perlu, karena seharusnya cukup

grep secara file.txt | wc -l

atau bisa juga menggunakan redirection

grep secara < file.txt | wc -l

Sebagian orang memandang penggunaan cat dalam kasus ini sangat tidak diperlukan, dan dianggap membuang resource (karena proses cat harus dieksekusi plus pipe harus dibuat). Orang-orang ini (sejak 1995) kadang-kadang memberikan “penghargaan” Useless Use of cat.

Saya termasuk orang yang suka menggunakan cat di 99% situasi. Dalam posting ini saya akan memberikan alasannya kenapa.

Pertama, klaim dari orang yang tidak suka menggunakan cat adalah bahwa ini menghabiskan resource. Penggunaan redirection akan lebih efisien. Klaim ini pasti benar, karena pasti akan ada overhead untuk mengeksekusi perintah cat dan melakukan komunikasi via pipe. Pertanyaannya adalah: berapa besar overheadnya?

Percobaan dengan file beberapa puluh megabyte di komputer saya yang cukup cepat, tidak menunjukkan perbedaan berarti (Intel Core2Duo 2.6 Ghz, memori 4 GB), karena itu saya mencoba di device yang sangat lambat yaitu router saya (memori 16 Mb, speed 200 Mhz, SD card 2 gb yang speednya kurang dari 1 mb/s). File table2 ukurannya 11.3 mb:

[email protected]:/mnt/sd# du -h table2.txt
11.3M   table2.txt

[email protected]:/mnt/sd# cat table2.txt  | time wc -l
500000
real    0m 31.50s
user    0m 2.63s
sys     0m 0.40s

[email protected]:/mnt/sd# time cat table2.txt  | wc -l  
real	0m 31.06s
user	0m 0.03s
sys	0m 14.83s
500000

[email protected]:/mnt/sd# time wc -l < table2.txt
500000
real    0m 30.79s
user    0m 2.49s
sys     0m 14.60s

Perlu dicatat bahwa shell yang digunakan di router adalah busybox. Pada busybox, perintah cat diimplementasikan oleh shell itu sendiri, bukan sebagai internal command, tapi dengan teknik symbolic link. Ini artinya shell tetap perlu mengeksekusi sebuah program untuk membentuk pipe. Perintah sudah dicoba berkali-kali untuk memastikan tidak ada efek cache, dan perbedaannya tidak lebih dari 1 detik.

Kedua, menurut pendapat saya (dan beberapa orang lain), cat akan memudahkan banyak hal, sehingga penghematan 1 detik tersebut tidak berarti dalam sebagian besar kasus setiap hari, dan kita bisa menghematnya dari kasus yang lain. Beberapa contoh:

jika kita memiliki file list.txt seperti ini:

ani
cinta
budi

perintah ini

cat list.txt |  xargs echo | sed -e "s/ /','/g;s/^/\('/g;s/$/\'\)/g"

akan menghasilkan

('ani','cinta','budi')

Sebenarnya cat di sini tidak perlu karena bisa memakai redirection

xargs echo < list.txt | sed -e "s/ /','/g;s/^/\('/g;s/$/\'\)/g"

Tapi misalnya jika kita ingin mengubah menjadi urutan sebaliknya, kita akan memakai

tac list.txt |  xargs echo | sed -e "s/ /','/g;s/^/\('/g;s/$/\'\)/g"

hasilnya:

('budi','cinta','ani')

Mengganti cat menjadi tac bisa dilakukan dengan sangat cepat. Di shell bash (default saat ini di aneka distro Linux), kita cukup menekan tombol atas (untuk mendapatkan perintah sebelumnya), menekan control-A (atau home untuk ke awal baris), alt-D (menghapus kata cat), dan mengetikkan tac.

Sama mudahnya jika Anda ingin mengganti tac dengan sort (untuk mengurutkan input) atau yang lain.

Hal lain yang kadang saya lakukan adalah memfilter isi sesuatu dari sebuah program yang prosesnya lama. Misalnya perintah untuk mendownload sesuatu dari web. Perintahnya kira-kira seperti ini:

lynx --dump http://example.com | grep pdf | aneka_proses_lain > newlist.txt

ketika masih mencoba-coba aneka proses untuk memfilter/mentransformasi input, menjalankan lynx berkali-kali membutuhkan waktu yang lama karena lynx harus melakukan koneksi, parsing, dsb. Cara yang paling cepat adalah dengan sementara menyimpan dulu di file:

lynx --dump http://example.com > test.txt

saya pakai

cat test.txt | grep pdf | aneka_proses_lain > newlist.txt

Jika sudah benar, saya cukup mengedit bagian cat test.txt dengan lynx --dump http://example.com.

Kasus lain lagi adalah ketika memproses file besar, saya biasanya akan mencoba dulu pada beberapa baris pertama dengan head:

head file.txt | perintah1 | perintah2

Jika sudah benar, saya cukup mengganti head dengan cat, sangat praktis.

Ketiga, jika Anda salah ketik ketika menggunakan < dan >, maka efeknya bisa berbahaya karena di sebagian besar keyboard kedua karakter tersebut sangat berdekatan. Contoh:

wc -l < test.txt

yang gunanya menghitung berapa baris file test.txt, versus

wc -l > test.txt

yang menghitung jumlah baris di standard input, lalu menuliskan hasilnya ke test.txt (menimpa isinya).

Di perintah UNIX, kita memang selalu harus berhati-hati, misalnya salah mengetik rm *.txt dengan rm * .txt efeknya sangat berbeda (yang pertama hanya menghapus file berakhiran .txt, yang kedua adalah menghapus semua file lalu menghapus file bernama .txt).

Karena suatu kesalahan kecil bisa berbahaya, umumnya orang akan sangat berhati-hati dan berusaha membuat kebiasaan yang tidak berbahaya. Contoh, mengetikkan !rm, akan mengeksekusi perintah terakhir yang berawalan rm, nah perintah ini berbahaya jika kita lupa bahwa perintah terakhir yang akan dieksekusi ternyata tidak sesuai harapan kita (karena lupa). Kebiasaan yang lebih baik adalah dengan menekan ctrl-r lalu mengetik rm (kita bisa melihat dulu perintahnya sebelum diekskusi).

Contoh lain, dalam pemrograman C, menuliskan a==0, atau 0==a sama saja. Tapi jika kita salah ketik, menuliskan 0=a merupakan ekspresi yang tidak valid, dan Anda akan segera menyadarinya, sedangkan ekspresi a=0 merupakan sesuatu yang valid.

Mungkin Anda adalah orang yang sangat teliti, tapi jika Anda mengirim perintah (via email) dan perintah itu diketikkan ulang oleh orang lain (misalnya karena pesannya dibaca via HP/Blackberry), akan lebih baik jika kita mengurangi risiko terjadi kesalahan ketik. Perhatikan saja berapa banyak orang yang bingung dengan orientasi / (slash) dan \ (backslash). Kasus lain adalah ketika memberikan instruksi yang memakai backtick (`), biasanya orang harus selalu menuliskan: “pakai backtick ya, yang disamping angka 1, bukan tanda kutip”. Hal ini bisa dihindari dengan menggunakan $(), misalnya

cd /lib/modules/`uname -r`

bisa dituliskan:

cd /lib/modules/$(uname -r)

Yang tidak akan membingungkan newbie. Sama halnya dengan < dan > yang mungkin salah dibanding dengan memakai cat.

Kapan sebaiknya tidak memakai cat?
Biasanya saya mengubah cat menjadi tanpa cat apabila ada serangkaian perintah yang ingin dijadikan shell script dan skrip itu akan memproses data yang besar di komputer yang lambat (atau dipakai banyak orang).

Baca juga link ini http://www.in-ulm.de/~mascheck/various/uuoc/ yang berisi informasi di mana cat benar-benar diperlukan (akan lebih efisien memakai cat dalam kasus-kasus tersebut).

Kesimpulan
Saya akan tetap menggunakan cat. Overhead cat sangat kecil, jadi resource yang terbuang juga sangat sedikit. Menggunakan cat biasanya lebih berguna daripada langsung menggunakan nama file atau redirection karena menghemat waktu jika kita ingin mengedit perintahnya. Penggunaan cat juga lebih aman karena tidak rawan salah.

Tambahan
Jika ada yang punya pengalaman di mana tidak memakai cat jauh lebih baik dari memakai cat, mohon dibagikan kepada saya dan dunia di komentar (atau tuliskan di blog Anda, lalu akan saya link). Kebetulan pada pengalaman saya 10 tahun memakai Linux, saya belum menemukan kasus di mana ada perbedaan performance yang jauh ketika memakai cat vs tidak memakai cat.

Leave a Reply

Your email address will not be published. Required fields are marked *