В Linux, как я могу проверить, идет ли вывод программы на работающий терминал или в файл? - PullRequest
8 голосов
/ 27 января 2010

Когда вы используете git , кажется, волшебным образом известно, идет ли стандартный выход через канал или в файл, когда он выводится на консоль. Например, если у вас включены цвета, и вы делаете

git status

это раскрасит вывод для различных категорий перечисленных файлов. Тем не менее, если вы делаете

git status | less

или

git status > status.txt

удаляет цветное форматирование linux , и вы видите только простой неокрашенный текст.

Как git определяет, будут ли выходные данные его команд отправляться в файл по сравнению с выходом на терминал?

Ответы [ 4 ]

14 голосов
/ 27 января 2010

isatty(int fd) проверит, ссылается ли fd на терминал или что-то еще. Это часть unistd.h в библиотеке GNU C.

Справочная страница: http://linux.die.net/man/3/isatty

Как отступление: если вы хотите читать из программы, использующей другую программу, но хотите обмануть isatty, думая, что ваша программа - человек, есть способ сделать это. Вы можете использовать псевдо-терминал (pty). Этот метод используется ожидают , например.

8 голосов
/ 27 января 2010

Это код C, демонстрирующий, как определить, перенаправлен ли стандартный вывод:

int main(int argc, char **argv){
    if (!isatty(fileno(stdout))){
      fprintf(stdout, "argv, argc, someone is redirecting me elsewhere...\n");
      return 1;
    }
    /* rest of C code here... */
}

Вот как git знает, идет ли вывод в терминал или в файл.

3 голосов
/ 27 января 2010

Может подтвердить, что git полагается на:

$ grep -ir "isatty" ./*
./builtin-commit.c:     if (isatty(0))
./builtin-config.c:         stdout_is_tty = isatty(1);
./builtin-pack-objects.c:   progress = isatty(2);
./builtin-prune-packed.c:   int opts = isatty(2) ? VERBOSE : 0;
./builtin-revert.c: if (isatty(0))
./builtin-shortlog.c:   if (!nongit && !rev.pending.nr && isatty(0))
./builtin-unpack-objects.c: quiet = !isatty(2);
./color.c:      stdout_is_tty = isatty(1);
./compat/winansi.c: if (!isatty(fileno(stream)))
./compat/winansi.c: if (!isatty(fileno(stream)))
./pack-redundant.c: if (!isatty(0)) {
./pager.c:  if (!isatty(1))
./pager.c:  if (isatty(2))
./remote-curl.c:    options.progress = !!isatty(2);
./transport.c:  args.no_progress = args.quiet || (!transport->progress && !isatty(1));
./transport-helper.c:   int no_progress = v < 0 || (!t->progress && !isatty(1));
./wt-status.c:   * will have checked isatty on stdout).

Запустить дерево исходников git.

Обратите внимание, что fds 0 = stdin, 1 = stdout, 2 = stderr по умолчанию, но, конечно, их можно перенаправить или закрыть (обычно, если вы демон, вы закрываете свои файловые дескрипторы и заново открываете те, которые хотите).

2 голосов
/ 21 мая 2013

Из сценария оболочки используйте флаг теста -t, применяемый к дескриптору файла 0 (стандартный ввод).

Примеры:

# Any Bourne-style shell
[ -t 0 ] && echo This is a terminal

# Modern interactive shells: ksh, bash, zsh
[[ -t 0 ]] && echo This is a terminal
...