Korzystam z ffmpeg, aby uzyskać meta informacje o klipie audio. Ale nie jestem w stanie tego zepsuć.
$ 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
...
Sprawdziłem, to wyjście ffmpeg jest kierowane do stderr.
$ ffmpeg -i 01-Daemon.mp3 2> /dev/null
Myślę więc, że grep nie może odczytać strumienia błędów, aby złapać pasujące linie. Jak możemy włączyć grep do odczytu strumienia błędów?
Za pomocą linku nixCraft przekierowałem standardowy strumień błędów do standardowego strumienia wyjściowego, a następnie grep zadziałał.
$ ffmpeg -i 01-Daemon.mp3 2>&1 | grep -i Duration
Duration: 01:15:12.33, start: 0.000000, bitrate: 64 kb/s
Ale co, jeśli nie chcemy przekierowywać stderr na stdout?
grep
io-redirection
ffmpeg
Andrew-Dufresne
źródło
źródło
grep
może działać tylko na standardowym wyjściu (chociaż nie mogę znaleźć źródła kanonicznego, które by to poparło), co oznacza, że każdy strumień musi zostać najpierw przekonwertowany na standardowe wyjście.grep
może działać tylko na standardowym wejściu . Jest to potok utworzony przez powłokę, który łączy stdin grep z stdout drugiego polecenia. A powłoka może tylko podłączyć stdout do stdin.Odpowiedzi:
Jeśli używasz,
bash
dlaczego nie zastosujesz anonimowych potoków, w skrócie stwórz to, co powiedział phunehe:ffmpeg -i 01-Daemon.mp3 2> >(grep -i Duration)
źródło
cp
wynikówcp -r dir* to 2> >(grep -v "svn")
>&2
np.command 2> >(grep something >&2)
2>
przekierowuje stderr do pliku, rozumiem. To czyta z pliku>(grep -i Duration)
. Ale plik nigdy nie jest przechowywany? Jak nazywa się ta technika, abym mógł przeczytać więcej na jej temat?Żadna ze zwykłych powłok (nawet zsh) nie zezwala na rury inne niż od standardowego do standardowego. Ale wszystkie powłoki w stylu Bourne'a obsługują zmianę przypisania deskryptorów plików (jak w
1>&2
). Możesz więc tymczasowo przekierować stdout na fd 3 i stderr na stdout, a później przywrócić fd 3 na stdout. Jeślistuff
produkuje jakieś wyjście na standardowym wyjściu, a niektóre na standardowym wyjściu, a chcesz zastosowaćfilter
na wyjściu błędu, pozostawiając standardowe wyjście nietknięte, możesz użyć{ stuff 2>&1 1>&3 | filter 1>&2; } 3>&1
.źródło
pipestatus
pomożeset -o pipefail
może być również pomocny tutaj, w zależności od tego, co chcesz zrobić ze statusem błędu. (Na przykład, jeśliset -e
włączyłeś się, aby nie powieść się na jakiekolwiek błędy, prawdopodobnieset -o pipefail
też chcesz ).set -e
włączyłem się, aby nie powieść żadnych błędów.rc
Powłoka umożliwia rurowe sys.stderr. Zobacz moją odpowiedź poniżej.Jest to podobne do „sztuczki z plikami tymczasowymi” phunehehe, ale zamiast tego używa nazwanego potoku, co pozwala uzyskać wyniki nieco bliżej, gdy są one wypisywane, co może być przydatne w przypadku długotrwałych poleceń:
W tej konstrukcji stderr zostanie skierowany do rury o nazwie „mypipe”. Ponieważ
grep
został wywołany z argumentem pliku, nie będzie szukał STDIN pod kątem danych wejściowych. Niestety, po zakończeniu będziesz musiał wyczyścić nazwaną rurę.Jeśli używasz Bash 4, istnieje składnia skrótu
command1 2>&1 | command2
, czylicommand1 |& command2
. Uważam jednak, że jest to wyłącznie skrót składniowy, nadal przekierowujesz STDERR do STDOUT.źródło
|&
składnia jest idealna do usuwania rozdętych śladów stosu Ruby stderr. Mogę w końcu grepować bez większych problemów.Odpowiedzi Gillesa i Stefana Lasiewskiego są dobre, ale ten sposób jest prostszy:
Zakładam, że nie chcesz
ffmpeg's
drukować standardowego.Jak to działa:
źródło
Zobacz poniżej skrypt używany w tych testach.
Grep może działać tylko na stdin, dlatego musisz przekonwertować strumień stderr w postać, którą Grep może analizować.
Zwykle stdout i stderr są drukowane na ekranie:
Aby ukryć stdout, ale nadal drukować stderr, wykonaj następujące czynności:
Ale grep nie będzie działał na stderr! Oczekuje się, że następujące polecenie ukryje wiersze zawierające „err”, ale tak nie jest.
Oto rozwiązanie.
Poniższa składnia Bash ukryje dane wyjściowe na stdout, ale nadal pokaże stderr. Najpierw przesyłamy stdout do / dev / null, a następnie konwertujemy stderr na stdout, ponieważ rury uniksowe będą działać tylko na stdout. Nadal możesz grepować tekst.
(Należy zauważyć, że powyższe polecenia jest inny czym
./command >/dev/null 2>&1
, co jest bardzo powszechne polecenia).Oto skrypt używany do testowania. Spowoduje to wydrukowanie jednej linii na standardowe wyjście i jednej linii na standardowe wyjście:
źródło
./stdout-stderr.sh 2>&1 >/dev/null | grep err
.Kiedy potokujesz wyjście jednego polecenia do drugiego (używając
|
), przekierowujesz tylko standardowe wyjście. To powinno wyjaśniać dlaczegonie wyświetla tego, co chciałeś (ale działa).
Jeśli nie chcesz przekierowywać wyjścia błędu na standardowe wyjście, możesz przekierować wyjście błędu do pliku, a następnie grep go później
źródło
it does work, though
, masz na myśli, że działa na twoim komputerze? Po drugie, jak zauważyłeś za pomocą potoku, możemy jedynie przekierować standardowe wyjście. Interesuje mnie funkcja polecenia lub bash, która pozwoli mi przekierować stderr. (ale nie sztuczka z plikiem tymczasowym)Możesz zamienić strumienie. Umożliwiłoby to przejście do
grep
oryginalnego standardowego strumienia błędów, a jednocześnie uzyskanie danych wyjściowych, które pierwotnie trafiły do standardowego wyjścia w terminalu:Działa to najpierw poprzez utworzenie nowego deskryptora pliku (3) otwartego dla wyjścia i ustawienie go na standardowy strumień błędów (
3>&2
). Następnie przekierowujemy błąd standardowy do standardowego wyjścia (2>&1
). Wreszcie standardowe wyjście jest przekierowywane do pierwotnego standardowego błędu, a nowy deskryptor pliku jest zamknięty (1>&3-
).W Twoim przypadku:
Testowanie:
źródło
rc
W tym przypadku lubię używać powłoki.Najpierw zainstaluj pakiet (jest mniej niż 1 MB).
Oto przykład, w jaki sposób odrzucisz
stdout
i potokujesz,stderr
aby grepowaćrc
:find /proc/ >[1] /dev/null |[2] grep task
Możesz to zrobić bez opuszczania Bash:
rc -c 'find /proc/ >[1] /dev/null |[2] grep task'
Jak zapewne zauważyłeś, składnia jest prosta, co czyni to moje preferowane rozwiązanie.
Możesz określić, który deskryptor pliku ma być umieszczony w nawiasach, tuż po znaku potoku.
Standardowe deskryptory plików są ponumerowane jako takie:
źródło
Odmiana przykładu podprocesu bash:
echo dwie linie do stderr i tee stderr do pliku, grep tee i potok z powrotem na standardowe wyjście
standardowe:
some.load.errors (np. stderr):
źródło
spróbuj tego polecenia
ceva -> tylko nazwa zmiennej (angielski = coś)
źródło
/tmp/$ceva
, lepiej niż zaśmiecanie bieżącego katalogu plikami tymczasowymi - i zakładasz, że bieżący katalog jest zapisywalny.