Я использую ffmpeg, чтобы получить метаинформацию аудиоклипа. Но я не могу понять это.
$ 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
...
Я проверил, этот вывод ffmpeg направлен на stderr.
$ ffmpeg -i 01-Daemon.mp3 2> /dev/null
Поэтому я думаю, что grep не может прочитать поток ошибок, чтобы поймать совпадающие строки. Как мы можем включить grep для чтения потока ошибок?
Используя ссылку nixCraft , я перенаправил стандартный поток ошибок в стандартный поток вывода, затем сработал grep.
$ ffmpeg -i 01-Daemon.mp3 2>&1 | grep -i Duration
Duration: 01:15:12.33, start: 0.000000, bitrate: 64 kb/s
Но что, если мы не хотим перенаправлять stderr в stdout?
grep
io-redirection
ffmpeg
Andrew-Dufresne
источник
источник
grep
может работать только на stdout (хотя я не могу найти канонический источник, подтверждающий это), что означает, что любой поток должен быть сначала преобразован в stdout.grep
может работать только на стандартный ввод. Это канал, созданный оболочкой, который соединяет stdin grep с stdout другой команды. И оболочка может только подключить стандартный вывод к стандартному вводу.Ответы:
Если вы используете,
bash
почему бы не использовать анонимные каналы, по сути, сокращение от того, что phunehehe сказал:ffmpeg -i 01-Daemon.mp3 2> >(grep -i Duration)
источник
cp
выводcp -r dir* to 2> >(grep -v "svn")
>&2
, например,command 2> >(grep something >&2)
2>
перенаправляет stderr в файл, я понял. Это читает из файла>(grep -i Duration)
. Но файл никогда не сохраняется? Как называется эта техника, чтобы я мог больше узнать об этом?Ни одна из обычных оболочек (даже zsh) не позволяет использовать каналы, отличные от stdout-stdin. Но все оболочки Bourne-style поддерживают переназначение дескриптора файла (как в
1>&2
). Таким образом, вы можете временно перевести stdout в fd 3 и stderr в stdout, а затем снова поместить fd 3 на stdout. Еслиstuff
выдает какой-то вывод на stdout и какой-то на stderr, и вы хотите применитьfilter
к выводу ошибки, оставляя стандартный вывод без изменений, вы можете использовать{ stuff 2>&1 1>&3 | filter 1>&2; } 3>&1
.источник
pipestatus
это поможетset -o pipefail
может быть полезным здесь, в зависимости от того, что вы хотите сделать с состоянием ошибки. (Например, если выset -e
включили с ошибкой при любых ошибках, вы, вероятно,set -o pipefail
также хотите .)set -e
включил, чтобы при любых ошибках.rc
Оболочка позволяет трубопроводов STDERR. Смотрите мой ответ ниже.Это похоже на «трюк временного файла» в phunehehe, но вместо этого использует именованный канал, позволяя вам получить результаты немного ближе к тому, когда они выводятся, что может пригодиться для длительных команд:
В этой конструкции stderr будет направлен на трубу с именем «mypipe». Так
grep
как был вызван с аргументом файла, он не будет искать STDIN для своего ввода. К сожалению, вам все равно придется очистить эту именованную трубу, как только вы закончите.Если вы используете Bash 4, существует сокращенный синтаксис для
command1 2>&1 | command2
, который естьcommand1 |& command2
. Тем не менее, я считаю, что это просто синтаксическое сокращение, вы все еще перенаправляете STDERR в STDOUT.источник
|&
синтаксис идеально подходит для очистки раздутых трассировок стека Ruby. Наконец-то я могу разобраться с ними без особых хлопот.Ответы Жиля и Стефана Ласевского хороши, но этот способ проще:
Я предполагаю, что вы не хотите
ffmpeg's
печатать стандартный вывод.Как это устроено:
источник
Ниже приведен скрипт, используемый в этих тестах.
Grep может работать только с stdin, поэтому вы должны преобразовать поток stderr в форму, которую Grep может проанализировать.
Обычно stdout и stderr выводятся на ваш экран:
Чтобы скрыть стандартный вывод, но все же вывести на печать стандартный вывод, сделайте следующее:
Но grep не будет работать на stderr! Можно ожидать, что следующая команда подавит строки, содержащие «err», но это не так.
Вот решение.
Следующий синтаксис Bash скроет вывод в stdout, но все равно покажет stderr. Сначала мы направляем stdout в / dev / null, затем преобразуем stderr в stdout, потому что каналы Unix будут работать только на stdout. Вы все еще можете получить текст.
(Обратите внимание , что приведенная выше команда является отличается то
./command >/dev/null 2>&1
, что является очень распространенной командой).Вот скрипт, используемый для тестирования. Это печатает одну строку в stdout и одну строку в stderr:
источник
./stdout-stderr.sh 2>&1 >/dev/null | grep err
.Когда вы перенаправляете вывод одной команды в другую (используя
|
), вы перенаправляете только стандартный вывод. Так что это должно объяснить, почемуне выводит то, что вы хотели (это работает, хотя).
Если вы не хотите перенаправлять вывод ошибок в стандартный вывод, вы можете перенаправить вывод ошибок в файл, а затем выполнить grep позже.
источник
it does work, though
Вы имеете в виду, что он работает на вашей машине? Во-вторых, как вы указали, используя pipe, мы можем только перенаправить стандартный вывод. Меня интересует какая-то команда или функция bash, которая позволяет мне перенаправлять stderr. (но не уловка временного файла)Вы можете поменять потоки. Это позволило бы вам перейти
grep
к исходному стандартному потоку ошибок, в то же время получая вывод, который первоначально был направлен на стандартный вывод в терминале:Это работает, сначала создав новый дескриптор файла (3), открытый для вывода, и установив его в стандартный поток ошибок (
3>&2
). Затем мы перенаправляем стандартную ошибку в стандартный вывод (2>&1
). Наконец стандартный вывод перенаправляется на исходную стандартную ошибку, и новый дескриптор файла закрывается (1>&3-
).В твоем случае:
Тестирование это:
источник
Мне нравится использовать
rc
оболочку в этом случае.Сначала установите пакет (это менее 1 МБ).
Это пример того, как вы бы сбросили
stdout
и передалиstderr
greprc
:find /proc/ >[1] /dev/null |[2] grep task
Вы можете сделать это, не выходя из Bash:
rc -c 'find /proc/ >[1] /dev/null |[2] grep task'
Как вы могли заметить, синтаксис прост, что делает это моим предпочтительным решением.
Вы можете указать, какой дескриптор файла вы хотите передать в скобках, сразу после символа канала.
Стандартные файловые дескрипторы нумеруются как таковые:
источник
Вариант на примере подпроцесса bash:
Выведите две строки в stderr и отправьте в файл stderr, grep и отправьте обратно в stdout
стандартный вывод:
some.load.errors (например, stderr):
источник
попробуйте эту команду
ceva -> просто имя переменной (english = что-то)
источник
/tmp/$ceva
лучше, чем засорять текущий каталог временными файлами - и вы предполагаете, что текущий каталог доступен для записи.