仅从命令行重定向读取 STDIN

Reading from STDIN from command line redirection only

我的目标是拥有一个可以从 C 文件重定向中获取用户输入的程序。

$ ./hello < input.txt

但是当没有重定向或参数时,程序将输出一条消息:

$ ./hello
There is nothing to read!

由于文件重定向直接进入标准输入,我正在使用 scanf 读取文件的内容。但是,当我在没有重定向的情况下启动程序时,scanf 等待输入,我的目标是仅从命令行上的重定向获取它,如果没有任何内容,它会输出消息

直到不可移植地检查 stdin 是否为 tty,shell 无法判断输入来自何处,它只能判断输入是否已经存在。你没有说你在哪个平台上,我假设你真正想要的只是/为了不阻塞读取/ - 你可以通过以非阻塞方式轮询 stdin 来实现:

#include <sys/select.h>
#include <stdio.h>
#include <unistd.h>

int poll_stdin() {
struct timeval tv;
fd_set fds;

    tv.tv_sec = 0;
    tv.tv_usec = 0;
    FD_ZERO(&fds);
    FD_SET(STDIN_FILENO, &fds); 
    select(STDIN_FILENO+1, &fds, NULL, NULL, &tv);
    return FD_ISSET(STDIN_FILENO, &fds);
}

size_t read_stdin(char *buf, size_t max) {
size_t n = 0;

   while ((n < max) && (poll_stdin())) {
      read(STDIN_FILENO, &buf[n++], 1);
   }
   if (n < max-1) buf[n] = '[=10=]';
   return n;
}

int main(int argc, char *argv[]) {
char buf[255];
size_t len;

   buf[255] = '[=10=]';
   len = read_stdin(buf, 255);
   if (len == 0) printf("No input!\n");
   else printf(">%s\n", buf);
   return 0;
}

输出:

dtrombley@squall:~$ echo 'Hello, world!' > hello.txt
dtrombley@squall:~$ ./main
No input!
dtrombley@squall:~$ ./main < hello.txt
>Hello, world!

使用 isatty()

这正是它的用途。

请注意,并非所有系统都提供健全的 isatty(),但任何声称符合 POSIX 的 *nixen 都可以正常工作。这是我当前的 *nixen 代码(适用于 C):

#include <stdbool.h>
#include <unistd.h>

bool my_isatty( int id )
{
  return (0 <= id) and (id <= 2) and isatty( id );
}

Windows 上有各种各样的皱纹,特别是如果你使用的是 MSYS2 shell(它使用管道实现命令 window,大声笑,所以你必须玩用一些低级 OS 的东西来检查。