Вот другое решение C, для которого только нужны STD C и меньше памяти:
#include <stdio.h>
int main(int argc, char **argv)
{
if (argc < 2 || !*argv[1]) {
puts("Argument missing.");
return 1;
}
char c = *argv[1], x = 0;
size_t count = 0;
while ((x = getc(stdin)) != EOF)
if (x == '\n') {
printf("%zd\n", count);
count = 0;
} else if (x == c)
++count;
return 0;
}
Рассмотрение двух команд по отдельности:
utility 2>&1 >output.log
Здесь, поскольку перенаправления обрабатываются слева -на -справа, стандартный поток ошибок сначала будет перенаправлен туда, куда направляется стандартный поток вывода (, возможно, на консоль ), а затем стандартный поток вывода будет перенаправлен в файл. Стандартный поток ошибок , а не будет перенаправлен в этот файл.
Видимым эффектом этого будет то, что вы получите результат стандартной ошибки на экране и результат стандартного вывода в файле.
utility 2>&1 | tee output.log
Здесь вы перенаправляете стандартную ошибку в то же место, что и стандартный поток вывода. Это означает, что оба потока будут переданы утилите tee
как один смешанный выходной поток, и что эти стандартные выходные данные будут сохранены в указанный файл с помощью tee
. Данные будут дополнительно воспроизводиться tee
в консоли (вот что делает tee
, дублирует потоки данных ).
Какой из них используется, зависит от того, чего вы хотите достичь.
Обратите внимание, что вы не сможете воспроизвести эффект второго конвейера только с помощью >
(, как в utility >output.log 2>&1
, который сохранил бы и стандартный вывод, и ошибку в файле, сначала перенаправляя стандартный вывод на output.log
. файл, а затем перенаправить стандартную ошибку туда, куда теперь идет стандартный вывод ). Вам нужно будет использовать tee
для получения данных в консоли, а также в выходном файле.
Дополнительные примечания:
видимый эффект первой команды,
utility 2>&1 >output.log
будет таким же, как
utility >output.log
Т. е. стандартный вывод идет в файл, а стандартная ошибка — в консоль.
Если бы в конце каждой из приведенных выше команд был добавлен дополнительный шаг обработки, была бы большая разница:
utility 2>&1 >output.log | more_stuff
utility >output.log | more_stuff
В первом конвейере more_stuff
получит исходный стандартный поток ошибок из utility
в качестве своих стандартных входных данных, а во втором конвейере, поскольку только результирующий стандартный поток вывода когда-либо отправляется по каналу., часть more_stuff
конвейера не получит ничего для чтения на своем стандартном вводе.
Удостоверьтесь, что прочитали комментарии к этому ответу — derobert.
Исходный ответ
2>&1 >output.log
средства сначала начинают отправлять, весь материал дескриптора файла 2 (стандартная погрешность) к дескриптору файла 1 (стандартный вывод) затем отправляют это в файл output.log
. Другими словами, отправьте стандартную погрешность и стандартный вывод к файлу журнала.
2>&1 | tee output.log
то же с 2>&1
бит, это комбинирует стандартный вывод и стандартную погрешность на потоке стандартного вывода. Это затем передает это по каналу через tee
программа, которая отправит ее стандартный вход в ее стандартный вывод (как cat
) и также в файл. Таким образом, это комбинирует эти два потока (ошибка и вывод), затем выводы это к терминалу и файлу.
Нижняя строка - то, что первое отправляет stderr
/stdout
в файл, в то время как второе отправляет его и в файл и в стандартный вывод (который является, вероятно, терминалом, если Вы не в другой конструкции, которая перенаправила стандартный вывод).
Я упоминаю, что последняя возможность, потому что у Вас может быть материал как:
(echo hello | tee xyzzy.txt) >plugh.txt
где ничто не заканчивается на терминале.
cat /doesnotexist 2>&1 >output.txt
- Вы будете видеть, посмотрите cat: /doesnotexist: No such file or directory
отображенный к терминалу и output.txt пустой файл. Порядок очередности и закрытие находятся в игре: 2>&1
(копируйте fd2 от текущего fd1), затем >output.txt
(перенаправьте fd1 к output.txt, не изменив ничто больше). Причина это 2>&1 |
отличается, из-за порядка очередности: |
прежде >
.
– Arcege
11.09.2011, 02:33
Первая команда сделает другую задачу:
После
2>&1 > output.log
старый STDOUT будет сохранен (скопированный) в STDERR, и затем STDOUT будет перенаправлен в файл.
Так, stdout перейдет к файлу, и stderr перейдет к консоли.
И в
2>&1 | tee output.log
оба потока будут перенаправлены для кладения для первого удара. Мишень копирует любой вход к своему stdout (консоль в Вашем случае) и зарегистрировать (output.log
).
И существует другая форма сначала:
> output.log 2>&1
это перенаправит и STDOUT и STDERR в файл.
Причина 2>&1 | tee
должен смочь получить и stdout и stderr к файлу журнала и видеть его на экране одновременно. Это могло быть сделано как >output.txt 2>&1 & tail -f
также, но Вы не знали бы, когда фоновая завершенная команда - является завершенной программой или является ею работающий без вывода. 2>&1 | tee
была общая идиома для программистов.
Вот пост суммировал выходные потоки Unix: http://www.devcodenote.com/2015/04/unix-outt-streams.html
фрагмент с поста:
Есть 3 Стандартные выходные потоки:
STDIN - Standard Input - Writes from an input device to the program
STDOUT - Standard Output - Writes program output to screen unless specified otherwise.
STDERR - Standard Error Output - Writes error messages. Also printed to the screen unless specified otherwise.
Давайте сначала посмотрим на пример кода:
#include <stdio.h>
main()
{
// message 1, on stdout (using printf)
printf("%s", "message 1, on stdout (using printf)\n");
// message 2, on stdout (using fprintf)
fprintf(stdout, "%s", "message 2, on stdout (using fprintf)\n");
// message 3, on stderr (using fprintf)
fprintf(stderr, "%s", "message 3, on stderr (using fprintf)\n");
}
Сравним результаты:./helloerror
+ файл :нет сообщения; консоль :сообщение 1,2,3;
./helloerror >error.txt
+ файл :сообщение 1,2; консоль :сообщение 3;
./helloerror 2>&1 >error.txt
+ файл :сообщение 1,2; консоль :сообщение 3;
+ то же, что и./helloerror >error.txt
./helloerror >error.txt 2>&1
+ файл :сообщение 3,1,2; консоль :нет сообщения;
+ обратите внимание, что сначала идет 3, затем 1, затем 2
./helloerror | tee error.txt 2>&1
+ файл :сообщение 1,2; консоль :сообщение 3,1,2;
+ обратите внимание, что сначала идет 3, затем 1, затем 2
./helloerror 2>&1 | tee error.txt
+ файл :сообщение 3,1,2; консоль :сообщение 3,1,2;
Для использования:./helloerror >error.txt 2>&1
-> если нужно, чтобы все (сообщения stdout+stderr )были в файле, но не выводились на консоль
./helloerror 2>&1 | tee error.txt
-> если нужно, чтобы все сообщения (stdout+stderr )были в файле и выводились на консоль