Ada beberapa perintah yang memfilter atau bertindak pada input, dan kemudian meneruskannya sebagai output, saya pikir biasanya untuk stdout
- tetapi beberapa perintah hanya akan mengambil stdin
dan melakukan apa pun yang mereka lakukan dengannya, dan tidak menghasilkan apa-apa.
Saya paling akrab dengan OS X dan jadi ada dua yang langsung terlintas di benak saya pbcopy
dan pbpaste
- yang merupakan cara mengakses clipboard sistem.
Bagaimanapun, saya tahu bahwa jika saya ingin mengambil stdout dan meludahkan output untuk pergi ke keduanya stdout
dan file maka saya bisa menggunakan tee
perintah. Dan saya tahu sedikit tentang itu xargs
, tetapi saya tidak berpikir itu yang saya cari.
Saya ingin tahu bagaimana saya dapat membagi stdout
untuk pergi antara dua (atau lebih) perintah. Sebagai contoh:
cat file.txt | stdout-split -c1 pbcopy -c2 grep -i errors
Mungkin ada contoh yang lebih baik daripada yang itu, tapi saya benar-benar tertarik mengetahui bagaimana saya bisa mengirim stdout ke perintah yang tidak menyampaikannya dan tetap menjaga agar stdout
tidak "diredam" - Saya tidak bertanya tentang cara cat
menyimpan file dan grep
bagian dari itu dan salin ke clipboard - perintah spesifik tidak begitu penting.
Juga - saya tidak bertanya bagaimana mengirim ini ke file dan stdout
- ini mungkin pertanyaan "duplikat" (maaf) tapi saya melihat beberapa dan hanya bisa menemukan yang serupa yang bertanya tentang bagaimana membagi antara stdout dan file - dan jawaban atas pertanyaan-pertanyaan itu tampaknya tee
, yang saya pikir tidak akan berhasil untuk saya.
Akhirnya, Anda mungkin bertanya "mengapa tidak membuat pbcopy hal terakhir dalam rantai pipa?" dan tanggapan saya adalah 1) bagaimana jika saya ingin menggunakannya dan masih melihat output di konsol? 2) bagaimana jika saya ingin menggunakan dua perintah yang tidak keluar stdout
setelah mereka memproses input?
Oh, dan satu hal lagi - saya sadar saya bisa menggunakan tee
dan bernama pipe ( mkfifo
) tapi saya berharap cara ini bisa dilakukan secara inline, secara ringkas, tanpa pengaturan sebelumnya :)
Jawaban:
Anda dapat menggunakan
tee
dan memproses substitusi untuk ini:Ini akan mengirim semua output
cat file.txt
kepbcopy
, dan Anda hanya akan mendapatkan hasilnyagrep
di konsol Anda.Anda dapat menempatkan beberapa proses di
tee
bagian:sumber
pbcopy
, tetapi layak disebutkan secara umum: apa pun output proses substitusi juga dilihat oleh segmen pipa berikutnya, setelah input asli; misalnya:seq 3 | tee >(cat -n) | cat -e
(membericat -n
nomor pada garis input,cat -e
menandai baris baru$
; Anda akan melihat bahwacat -e
diterapkan pada input asli (pertama) dan (kemudian) dari outputcat -n
). Output dari berbagai proses penggantian akan tiba dalam urutan non-deterministik.>(
satunya yang berfungsi dibash
. Jika Anda mencobanya menggunakan misalnyash
itu tidak akan berhasil. Penting untuk membuat pemberitahuan ini.dash
, yang bertindak sepertish
di Ubuntu, tidak mendukungnya, dan bahkan Bash sendiri menonaktifkan fitur ketika dipanggil sebagaish
atau ketikaset -o posix
sedang berlaku. Namun, bukan hanya Bash yang mendukung proses penggantian:ksh
danzsh
mendukung mereka juga (tidak yakin tentang orang lain).bash
danksh
-zsh
tampaknya tidak mengirim output dari penggantian proses keluaran melalui pipa (bisa dibilang, itu lebih disukai , karena tidak mencemari apa yang dikirim ke segmen pipa berikutnya - meskipun masih dicetak ). Dalam semua shell yang disebutkan, bagaimanapun, umumnya bukan ide yang baik untuk memiliki satu saluran pipa di mana output stdout reguler dan output dari substitusi proses dicampur - pemesanan output tidak akan dapat diprediksi, dengan cara yang mungkin hanya permukaan jarang atau dengan besar set data keluaran.Anda dapat menentukan beberapa nama file
tee
, dan selain itu output standar dapat disalurkan ke dalam satu perintah. Untuk mengirim output ke beberapa perintah, Anda perlu membuat beberapa pipa dan menentukan masing-masing sebagai satu outputtee
. Ada beberapa cara untuk melakukan ini.Substitusi proses
Jika shell Anda adalah ksh93, bash atau zsh, Anda dapat menggunakan subtitusi proses. Ini adalah cara untuk melewatkan pipa ke perintah yang mengharapkan nama file. Shell membuat pipa dan memberikan nama file seperti
/dev/fd/3
ke perintah. Nomornya adalah deskriptor file yang terhubung dengan pipa. Beberapa varian unix tidak mendukung/dev/fd
; pada ini, pipa bernama digunakan sebagai gantinya (lihat di bawah).Deskriptor file
Di setiap shell POSIX, Anda dapat menggunakan banyak deskriptor file secara eksplisit. Ini memerlukan varian unix yang mendukung
/dev/fd
, karena semua kecuali satu dari outputtee
harus ditentukan oleh nama.Bernama pipa
Metode paling dasar dan portabel adalah dengan menggunakan pipa bernama . Kelemahannya adalah Anda perlu menemukan direktori yang bisa ditulis, membuat pipa, dan membersihkannya setelah itu.
sumber
tee "$tmp_dir/f1" "$tmp_dir/f2" | command3
harus pasticommand3 | tee "$tmp_dir/f1" "$tmp_dir/f2"
, karena Anda ingin stdout daricommand3
pipatee
, bukan? Saya menguji versi Anda di bawahdash
dantee
memblokir menunggu input tanpa batas, tetapi beralih urutan menghasilkan hasil yang diharapkan.command
,command2
dancommand3
.<command> | bash -c 'tee >(command1) >(command2) | command3'
. Ini membantu dalam kasus saya.Cukup mainkan dengan proses substitusi.
grep
adalah dua binari yang memiliki output yang sama darimycommand_exec
input spesifik prosesnya.sumber
Jika Anda menggunakan
zsh
maka Anda dapat memanfaatkan kekuatanMULTIOS
fitur, yaitu menyingkirkantee
perintah sepenuhnya:hanya akan menulis output
uname
ke dua file berbeda:file1
danfile2
, apa yang setara denganuname | tee file1 >file2
Demikian pula pengalihan input standar
setara dengan
cat file1 file2 | wc -l
(harap dicatat bahwa ini tidak sama denganwc -l file1 file2
, yang kemudian menghitung jumlah baris dalam setiap file secara terpisah).Tentu saja Anda juga dapat menggunakan
MULTIOS
untuk mengarahkan kembali output bukan ke file tetapi ke proses lain, menggunakan substitusi proses, misalnya:sumber
MULTIOS
adalah opsi yang AKTIF secara default (dan dapat dimatikan denganunsetopt MULTIOS
).Untuk output yang cukup kecil yang dihasilkan oleh suatu perintah, kita dapat mengalihkan output ke file sementara, dan mengirimkan file-file sementara ke perintah dalam loop. Ini bisa berguna ketika urutan perintah yang dieksekusi mungkin penting.
Skrip berikut, misalnya, dapat melakukannya:
Uji berjalan pada Ubuntu 16.04 dengan
/bin/sh
sebagaidash
shell:sumber
Abadikan perintah
STDOUT
ke variabel dan gunakan kembali sebanyak yang Anda suka:Jika Anda perlu menangkap
STDERR
juga, gunakan2>&1
di akhir perintah, seperti:sumber
Ini mungkin berguna: http://www.spinellis.gr/sw/dgsh/ (diarahkan graph shell) Sepertinya pengganti bash mendukung sintaks yang lebih mudah untuk perintah "multipipe".
sumber
Berikut adalah solusi parsial cepat dan kotor, kompatibel dengan semua shell termasuk
busybox
.Masalah yang lebih sempit yang dipecahkannya adalah: mencetak komplet
stdout
ke satu konsol, dan memfilternya di konsol lain, tanpa file sementara atau pipa bernama.tty
. Mari kita asumsikan/dev/pty/2
.the_program | tee /dev/pty/2 | grep ImportantLog:
Anda mendapatkan satu log lengkap, dan satu yang difilter.
sumber