відобразити STDOUT перед STDERR?


9

Я новачок у баші, і я не можу за все життя зрозуміти, як запустити певну команду, припустимо ./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

Вам потрібно буде тримати дедалі більш жорсткий вихід десь, щоб мати змогу відобразити його в кінці.

На думку приходить файл :

fff 2> file; cat file >&2

Або пам'ять (тут використовується spongeз moreutils):

{ fff 2>&1 >&3 3>&- | sponge >&2 3>&-; } 3>&1
  • {...} 3>&1: у {...}файлі дескриптора (fd) 3 вказує на той же ресурс, що і вихідний stdout (тому ми можемо використовувати його для відновлення stdout для fff).
  • fff <redirs> | sponge <redirs>, fffі spongeрозпочався одночасно (при <redirs>застосуванні незалежно), коли fffstdout йде до труби, а spongesdin - другий кінець труби.
  • 2>&1: fd 2 of fff(stderr) вказує на те саме, що і на 1: труба в цій точці, тому fffпомилка переходить spongeчерез цю трубу.
  • >&3: тепер stdout вказує на початковий stdout (перенаправлення назад на те, що було)
  • 3>&-: ми закриваємо fd 2, який fffне потрібен
  • spongeнакопичує свій вхід і лише відображає його (на своєму stdout, який був перенаправлений >&2на той самий ресурс, що і stderr) після того, як він виявив eof на своєму stdin (припускається, що коли він fffприпиняється і вже записав увесь свій вихід у stdout).

Якщо spongeвін не встановлений, його можна замінити на perl -0777 -pe ''. З -pe '', perlчитає одночасно запис із свого входу і записує його на stdout. -0777це режим "slurp", де запис (лише один у цьому випадку) - це весь вхід.


Будь ласка, розбийте його, якщо у вас є час!
Джордж Удосен

Чи можемо ми використовувати teeзамість sponge...?
Джордж Васильоу

@GeorgeUdosen див. Редагувати.
Стефан Шазелас

1
@GeorgeVasiliou, teeне містить даних, він записує їх, як тільки їх читає.
Стефан Шазелас

2
@MeOw: Це добре, але, як показує третій рядок відповіді Стефана, вам не потрібно зберігати stdout; просто робити 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.