отображать STDOUT перед STDERR?


9

Я новичок в bash и не могу на всю жизнь понять, как запустить определенную команду, предположить ./fffи напечатать обычные stdouts перед stderr (я сам не понимаю смысла)

например

$ printf "I am a\ndrill\n" > fff; 
$ cat fff nofile fff nofile fff

I am a
drill
cat: nofile: No such file or directory
I am a
drill
cat: nofile: No such file or directory
I am a
drill

нужно напечатать как:

I am a
drill
I am a
drill
I am a
drill
cat: nofile: No such file or directory
cat: nofile: No such file or directory

Я понимаю, что мне нужно сначала перенаправить вывод в файл, а затем добавить ошибку в тот же файл, однако это вывод, который я получаю для

$ cat ./foo nofile ./foo nofile ./foo <<< $(touch fin) > see 2>> see 

I am a
drill
I am a
drill
I am a
drill
ectory
cat: nofile: No such file or directory

2
Действительно catли заменить «а» на «некоторые»?
Дмитрий Григорьев

о черт, я мог испортить строку. Я отредактирую это сразу @DmitryGrigoryev
MeOw

Ответы:


18

В любом случае вам нужно будет где-то держать вывод stderr, чтобы иметь возможность отображать его в конце.

Файл приходит на ум:

fff 2> file; cat file >&2

Или память (здесь используется spongeиз moreutils):

{ fff 2>&1 >&3 3>&- | sponge >&2 3>&-; } 3>&1
  • {...} 3>&1: в {...}дескрипторе файла (fd) 3 указывает на тот же ресурс, что и исходный стандартный вывод (так что мы можем использовать его для восстановления стандартного вывода fff).
  • fff <redirs> | sponge <redirs>, fffИ spongeначалась параллельно (с <redirs>применяться независимо друг от друга) с fff«ы стандартный вывод происходит в трубе, а sponge» STDIN с будучи на другом конце трубы.
  • 2>&1: fd 2 of fff(stderr) указывает на то же самое, что и на 1: канал в этой точке, поэтому fffошибка идет spongeчерез этот канал.
  • >&3: теперь стандартный вывод указывает на исходный стандартный вывод (перенаправьте обратно к тому, что было)
  • 3>&-: закрываем fd 2, который fffне нужен
  • spongeнакапливает свои входные данные и только отображает их (на своем стандартном выводе, который был перенаправлен >&2на тот же ресурс, что и stderr) после того, как он обнаружил eof на своем стандартном входе (предполагается, что он fffзавершается, и уже записал весь свой вывод на свой стандартный вывод).

Если spongeне установлен, вы можете заменить его на perl -0777 -pe ''. С -pe '', perlчитает одну запись за раз с ее ввода и записывает ее на стандартный вывод. -0777является режимом slurp, где (только одна в этом случае) запись представляет собой весь ввод.


Пожалуйста, сломайте его, если у вас есть время!
Джордж Удосен

Можем ли мы использовать teeвместо sponge...?
Георгий Васильев

@ GeorgeUdosen см. Редактировать.
Стефан Шазелас

1
@GeorgeVasiliou, teeне хранит данные, пишет их, как только читает.
Стефан Шазелас

2
@MeOw: Это хорошо, но, как показывает третья строка ответа Стефана, вам не нужно сохранять стандартный вывод; просто делай cat foo nofile foo nofile foo 2> ferr.txt; cat ferr.txt. (И вы , вероятно , не хочу , чтобы использовать >>.) Кроме того , Stéphane делает отличную точку , что вы , вероятно , следует сделать , cat ferr.txt >&2чтобы записать информацию Stderr в стандартный поток ошибок.
G-Man говорит: «Восстановите Монику»
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.