Perintah terminal itu kecil-kecil: grep cuma menyaring baris, wc cuma menghitung, sort cuma mengurutkan. Pipe (|) menyambungkan mereka jadi satu rangkaian, dan redirection (>, >>, 2>) mengarahkan hasilnya ke file, bukan ke layar. Mirip ban berjalan di pabrik: tiap pekerja mengambil barang dari ban, mengerjakan satu tugas, lalu menaruhnya lagi untuk pekerja berikutnya. Di ujung ban, barangnya dipajang di etalase (layar), atau masuk kardus (file) kalau kamu minta.
🧪 Tebakan cepat: kamu menjalankan
echo "deploy" > catatan.txtdua kali. Isicatatan.txtjadi satu baris atau dua baris? Tebak dulu, jawabannya ada di bagian "Redirect: simpan hasil ke file".
Tiga saluran: stdin, stdout, stderr
Setiap program yang jalan punya tiga saluran data, masing-masing dengan nomor:
| Nomor | Nama | Isinya | Defaultnya |
|---|---|---|---|
| 0 | stdin (standard input) | data yang masuk ke program | keyboard |
| 1 | stdout (standard output) | hasil normal | layar |
| 2 | stderr (standard error) | pesan error | layar |
stdout dan stderr sama-sama muncul di layar, jadi kelihatannya satu. Padahal itu dua saluran terpisah, dan bedanya baru terasa waktu kamu memakai pipe dan redirect.
Pipe: output kiri jadi input kanan
Contohnya app.log, log sebuah server yang isinya 6 baris:
INFO: Server started
ERROR: Database timeout
INFO: Request handled
ERROR: File not found
ERROR: Permission denied
INFO: Cache cleared
Ada berapa baris ERROR?
$ cat app.log | grep ERROR | wc -l
3
| Tahap | Perintah | Yang dia keluarkan |
|---|---|---|
| 1 | cat app.log |
6 baris isi file |
| 2 | grep ERROR |
3 baris yang mengandung ERROR |
| 3 | wc -l |
3, jumlah baris yang dia terima |
cat app.logmencetak isi file ke stdout-nya.|menyambungkan stdout perintah kiri ke stdin perintah kanan. Jadigrepgak membuka file apa pun, dia membaca 6 baris kirimancat.grep ERRORcuma meneruskan baris yang mengandung teksERROR.wc -lmenghitung baris (-l= lines) lalu mencetak angkanya. Dia ujung rangkaian, jadi angkanya muncul di layar. (Di macOS, angkanya diawali beberapa spasi.)
Urutannya penting. cat app.log | wc -l | grep ERROR gak mencetak apa-apa: wc -l sudah mengubah 6 baris jadi angka 6, dan angka itu gak mengandung ERROR.
Satu lagi: wc -c menghitung byte, dan echo selalu menambahkan karakter baris baru di akhir. Jadi echo "hello" | wc -c hasilnya 6: 5 huruf ditambah 1 baris baru.
Redirect: simpan hasil ke file
$ echo "deploy pertama" > catatan.txt
$ echo "deploy kedua" >> catatan.txt
$ cat catatan.txt
deploy pertama
deploy kedua
$ echo "deploy ketiga" > catatan.txt
$ cat catatan.txt
deploy ketiga
>mengarahkan stdout ke file. Kalau file-nya belum ada, dibuat. Kalau sudah ada, isinya dikosongkan dulu, baru ditulis.>>juga mengarahkan ke file, tapi menambah di akhir. Isi lamanya tetap.- Yang masuk ke file gak muncul di layar lagi.
Jadi echo "deploy" > catatan.txt dua kali tetap menghasilkan satu baris: tulisan kedua menimpa yang pertama. Mau dua baris, pakai >>. Itu jawaban tebakannya.
Pipe dan redirect bisa digabung. Redirect stdout ditulis di ujung perintah terakhir:
cat app.log | grep ERROR > hasil.txt # 3 baris ERROR masuk hasil.txt, layar kosong
cat app.log | grep ERROR | wc -l >> hasil.txt # angka 3 ditambahkan di akhir hasil.txt
Kebalikannya ada <: isi file dikirim ke stdin. wc -l < app.log mencetak 6 saja, sedangkan wc -l app.log mencetak 6 app.log, karena kali ini wc tahu nama file-nya.
Error punya jalurnya sendiri
Kalau cat diminta membaca file yang gak ada, pesan error-nya keluar lewat stderr:
$ cat app.log lama.log | grep ERROR | wc -l
cat: lama.log: No such file or directory
3
Pipe cuma mengalirkan stdout. Pesan error dari cat gak masuk ke grep, dia langsung muncul di layar, dan hasilnya tetap 3. Untuk memindahkan stderr, tulis nomornya di depan >:
cat app.log lama.log 2> error.txt | grep ERROR | wc -l # layar cuma 3, error masuk error.txt
find / -name "*.conf" 2> /dev/null # buang semua pesan error
npm run build > build.log 2>&1 # stdout dan stderr ke file yang sama
2>menempel ke perintah tempat dia ditulis. Error-nya datang daricat, jadi2> error.txtditulis setelahcat, bukan di ujung rangkaian./dev/nulladalah tong sampah: apa pun yang ditulis ke sana hilang.2>&1artinya "stderr ikut ke tempat stdout sekarang". Urutannya penting:> build.log 2>&1mengirim dua-duanya ke file, sedangkan2>&1 > build.logmembuat error tetap ke layar. Di bash,&> build.logadalah singkatan untuk yang pertama.teememecah aliran jadi dua:npm run build | tee build.logmenampilkan output di layar sekaligus menyimpannya ke file.
Pipe di JavaScript: fungsi pipe
Ide yang sama bisa ditulis di JavaScript, dan itulah latihan pelajaran ini. pipe(f, g) mengembalikan function baru: input masuk ke f, lalu hasil f masuk ke g.
function pipe(...fns) {
return (input) => fns.reduce((value, fn) => fn(value), input);
}
const logLines = [
"INFO: Server started",
"ERROR: Database timeout",
"INFO: Request handled",
"ERROR: File not found",
"ERROR: Permission denied",
"INFO: Cache cleared"
];
const filterErrors = (lines) => lines.filter((l) => l.includes("ERROR")); // seperti grep ERROR
const countLines = (lines) => lines.length; // seperti wc -l
const countErrors = pipe(filterErrors, countLines);
console.log(countErrors(logLines)); // 3
...fnsmengumpulkan semua function yang dikirim kepipejadi satu array.pipebelum menjalankan apa-apa. Dia mengembalikan function yang menungguinput.reduce(dari pelajaran array methods) membawa nilai dari satu function ke function berikutnya.valueawalnyainput, lalu diganti hasil tiap function.
pipe((n) => n + 1, (n) => n * 2)(3) hasilnya 8: 3 masuk ke function pertama jadi 4, lalu 4 masuk ke function kedua jadi 8. Urutannya dari kiri ke kanan, sama seperti | di terminal. Dan pipe()(5) tanpa function sama sekali mengembalikan 5: reduce gak punya apa pun untuk dijalankan, jadi yang keluar nilai awalnya.
⚠️ Jebakan yang sering ketemu
>ke file yang sedang dibaca.sort data.txt > data.txtmengosongkandata.txtsebelumsortsempat membacanya, jadi hasilnya file kosong. Tulis ke file lain dulu.- Mengira error ikut masuk pipe atau file.
|dan>cuma membawa stdout. Pesan error tetap muncul di layar sampai kamu memakai2>. - Salah urutan tahap. Tiap tahap cuma melihat output tahap sebelumnya.
wc -ldi tengah rangkaian mengubah semua baris jadi satu angka. - Di latihan, function jalan dari kanan, atau
reducetanpa nilai awal.pipe(tambahSatu, kaliDua)(3)harus8, bukan7. Latihannya juga mengecek kamu memakaireduce, danpipe()(5)harus mengembalikan5, jadi kiriminputsebagai nilai awal.
TL;DR: Tiap program punya stdin (0), stdout (1) dan stderr (2). | menyambungkan stdout kiri ke stdin kanan: cat app.log | grep ERROR | wc -l mencetak 3. > menulis stdout ke file dan menimpa isinya, >> menambah di akhir, < membaca file sebagai stdin. Error lewat stderr, gak ikut pipe atau >; pindahkan dengan 2> file, buang dengan 2> /dev/null, gabungkan dengan > file 2>&1. echo "hello" | wc -c hasilnya 6 karena ada baris baru. Di JavaScript, pipe(...fns) mengembalikan (input) => fns.reduce((value, fn) => fn(value), input), dari kiri ke kanan.