Saya menggunakan ffmpeg untuk mendapatkan info meta dari klip audio. Tapi saya tidak bisa menerimanya.
$ ffmpeg -i 01-Daemon.mp3 |grep -i Duration
FFmpeg version SVN-r15261, Copyright (c) 2000-2008 Fabrice Bellard, et al.
configuration: --prefix=/usr --bindir=/usr/bin
--datadir=/usr/share/ffmpeg --incdir=/usr/include/ffmpeg --libdir=/usr/lib
--mandir=/usr/share/man --arch=i386 --extra-cflags=-O2
...
Saya memeriksa, output ffmpeg ini diarahkan ke stderr.
$ ffmpeg -i 01-Daemon.mp3 2> /dev/null
Jadi saya pikir grep tidak dapat membaca aliran kesalahan untuk menangkap garis yang cocok. Bagaimana kita bisa mengaktifkan grep untuk membaca aliran kesalahan?
Menggunakan tautan nixCraft , saya mengarahkan aliran kesalahan standar ke aliran keluaran standar, lalu grep bekerja.
$ ffmpeg -i 01-Daemon.mp3 2>&1 | grep -i Duration
Duration: 01:15:12.33, start: 0.000000, bitrate: 64 kb/s
Tetapi bagaimana jika kita tidak ingin mengarahkan stderr ke stdout?
grep
io-redirection
ffmpeg
Andrew-Dufresne
sumber
sumber
grep
hanya dapat beroperasi pada stdout (Meskipun saya tidak dapat menemukan sumber kanonik untuk mendukung itu), yang berarti bahwa setiap aliran perlu dikonversi ke stdout terlebih dahulu.grep
hanya bisa beroperasi di stdin. Ini adalah pipa yang dibuat oleh shell yang menghubungkan stdin grep ke stdout perintah lain. Dan shell hanya dapat menghubungkan stdout ke stdin.Jawaban:
Jika Anda menggunakan
bash
mengapa tidak menggunakan pipa anonim, intinya singkatan untuk apa yang dikatakan phunehehe:ffmpeg -i 01-Daemon.mp3 2> >(grep -i Duration)
sumber
cp
outputcp -r dir* to 2> >(grep -v "svn")
>&2
, misalnyacommand 2> >(grep something >&2)
2>
pengalihan stderr ke file, saya mengerti. Ini membaca dari file>(grep -i Duration)
. Tetapi file tidak pernah disimpan? Apa nama teknik ini sehingga saya bisa membaca lebih lanjut tentang itu?Tak satu pun dari kerang yang biasa (bahkan zsh) mengizinkan pipa selain dari stdout ke stdin. Tetapi semua shell Bourne-style mendukung penugasan kembali deskriptor file (seperti pada
1>&2
). Jadi, Anda dapat sementara mengalihkan stdout ke fd 3 dan stderr ke stdout, dan kemudian mengembalikan fd 3 ke stdout. Jikastuff
menghasilkan beberapa output pada stdout dan beberapa output pada stderr, dan Anda ingin menerapkanfilter
pada output kesalahan membiarkan output standar tidak tersentuh, Anda dapat menggunakan{ stuff 2>&1 1>&3 | filter 1>&2; } 3>&1
.sumber
pipestatus
akan membantuset -o pipefail
dapat membantu di sini, tergantung pada apa yang ingin Anda lakukan dengan status kesalahan. (Misalnya, jika Anda telahset -e
mengaktifkan kegagalan pada kesalahan apa pun, Anda mungkinset -o pipefail
juga menginginkannya .)set -e
mengaktifkan gagal pada kesalahan apa pun.rc
shell memungkinkan pipa stderr. Lihat jawaban saya di bawah ini.Ini mirip dengan "file temp trik" phunehehe, tetapi menggunakan pipa bernama sebagai gantinya, memungkinkan Anda untuk mendapatkan hasil yang sedikit lebih dekat dengan ketika mereka dihasilkan, yang dapat berguna untuk perintah yang berjalan lama:
Dalam konstruksi ini, stderr akan diarahkan ke pipa bernama "mypipe". Karena
grep
telah dipanggil dengan argumen file, ia tidak akan meminta input dari STDIN. Sayangnya, Anda masih harus membersihkan pipa bernama itu setelah Anda selesai.Jika Anda menggunakan Bash 4, ada sintaks pintasan untuk
command1 2>&1 | command2
, yaitucommand1 |& command2
. Namun, saya percaya bahwa ini murni cara pintas sintaksis, Anda masih mengarahkan ulang STDERR ke STDOUT.sumber
|&
sintaks yang sempurna untuk membersihkan Ruby jejak stderr tumpukan kembung. Saya akhirnya bisa menangkap mereka tanpa terlalu banyak kesulitan.Jawaban Gilles dan Stefan Lasiewski sama-sama baik, tetapi cara ini lebih sederhana:
Saya berasumsi Anda tidak ingin
ffmpeg's
stdout dicetak.Bagaimana itu bekerja:
sumber
Lihat di bawah untuk skrip yang digunakan dalam tes ini.
Grep hanya dapat beroperasi pada stdin, jadi karena itu Anda harus mengonversi aliran stderr dalam bentuk yang dapat diurai Grep.
Biasanya, stdout dan stderr keduanya dicetak ke layar Anda:
Untuk menyembunyikan stdout, tetapi tetap cetak stderr lakukan ini:
Tetapi grep tidak akan beroperasi pada stderr! Anda akan mengharapkan perintah berikut untuk menekan baris yang mengandung 'err', tetapi tidak.
Inilah solusinya.
Sintaks Bash berikut akan menyembunyikan output ke stdout, tetapi masih akan menampilkan stderr. Pertama kita mem-pipe stdout ke / dev / null, lalu kita mengonversi stderr ke stdout, karena pipa Unix hanya akan beroperasi di stdout. Anda masih dapat menerima teks.
(Perhatikan bahwa perintah di atas berbeda dengan itu
./command >/dev/null 2>&1
, yang merupakan perintah yang sangat umum).Inilah skrip yang digunakan untuk pengujian. Ini mencetak satu baris ke stdout dan satu baris ke stderr:
sumber
./stdout-stderr.sh 2>&1 >/dev/null | grep err
.Ketika Anda menyalurkan output dari satu perintah ke perintah lainnya (menggunakan
|
), Anda hanya mengarahkan keluaran standar. Jadi itu harus menjelaskan alasannyatidak menampilkan apa yang Anda inginkan (itu berhasil, meskipun).
Jika Anda tidak ingin mengarahkan output kesalahan ke output standar, Anda dapat mengarahkan output kesalahan ke file, lalu ambil nanti
sumber
it does work, though
Anda maksud itu berfungsi pada mesin Anda? Kedua, seperti yang Anda tunjukkan menggunakan pipa, kita hanya bisa mengarahkan ulang stdout. Saya tertarik pada beberapa fitur perintah atau bash yang akan membiarkan saya mengarahkan stderr. (tapi bukan trik temp file)Anda dapat menukar streaming. Ini akan memungkinkan Anda ke
grep
stream kesalahan standar asli sambil tetap mendapatkan output yang awalnya pergi ke output standar di terminal:Ini bekerja dengan terlebih dahulu membuat file descriptor baru (3) terbuka untuk output dan mengaturnya ke aliran kesalahan standar (
3>&2
). Kemudian kami mengarahkan kesalahan standar ke output standar (2>&1
). Akhirnya keluaran standar dialihkan ke kesalahan standar asli, dan deskriptor file baru ditutup (1>&3-
).Dalam kasus Anda:
Mengujinya:
sumber
Saya suka menggunakan
rc
shell dalam hal ini.Pertama instal paket (kurang dari 1MB).
Ini adalah contoh bagaimana Anda akan membuang
stdout
dan memasang pipastderr
untuk menerimarc
:find /proc/ >[1] /dev/null |[2] grep task
Anda dapat melakukannya tanpa meninggalkan Bash:
rc -c 'find /proc/ >[1] /dev/null |[2] grep task'
Seperti yang mungkin telah Anda perhatikan, sintaksinya langsung, yang menjadikan ini solusi pilihan saya.
Anda bisa menentukan deskriptor file mana yang ingin Anda perpipkan di dalam tanda kurung, tepat setelah karakter pipa.
Deskriptor file standar diberi nomor seperti itu:
sumber
Variasi pada contoh sub proses bash:
gema dua baris ke stderr dan tee stderr ke file, ambil tee dan pipa kembali ke stdout
stdout:
some.load.errors (misalnya stderr):
sumber
coba perintah ini
ceva -> hanya nama variabel (bahasa Inggris = sesuatu)
sumber
/tmp/$ceva
, lebih baik daripada mengotori direktori saat ini dengan file sementara - dan Anda mengasumsikan bahwa direktori saat ini dapat ditulis.