如果输入重定向执行操作 [英] Perform action if input is redirected
问题描述
我想知道我应该怎么去了解,如果我的输入被重定向到C程序中执行操作。例如,假设我有我的编译的程序前卫,我重定向输入input.txt的来了(我 ./ PROG< input.txt的
)。
I want to know how I should go about performing an action in a C program if my input was redirected. For example, say I have my compiled program "prog" and I redirect an input "input.txt" to it (I do ./prog < input.txt
).
如何在code检测呢?
How do I detect this in code?
推荐答案
您不能在一般情况下,判断是否输入被重定向;但你可以根据是什么类型的文件标准输入的区分。如果一直没有重定向,这将是一个终端;或者它可能已被设置为一个管道猫富| ./prog
,或者从一个普通文件重定向(如你的例子),或从多种类型的特殊文件( ./ PROG化合物的一重定向; /开发/ sda1的
从块特殊文件重定向它,等等)。
You can't, in general, tell if input has been redirected; but you can distinguish based on what type of file stdin is. If there has been no redirection, it will be a terminal; or it could have been set up as a pipe cat foo | ./prog
, or a redirection from a regular file (like your example), or a redirection from one of a number of types of special files (./prog </dev/sda1
redirecting it from a block special file, etc).
所以,如果你想确定标准输入是终端(TTY),你可以使用的 isatty
:
So, if you want to determine if stdin is a terminal (TTY), you can use isatty
:
#include <unistd.h>
#include <stdio.h>
int main(int argc, char **argv) {
if (isatty(STDIN_FILENO))
printf("stdin is a tty\n");
else
printf("stdin is not a tty\n");
return 0;
}
如果您希望其他案件进行区分(如管道,块特殊文件,等等),你可以使用的 FSTAT
提取一些更多的文件类型的信息。请注意,这实际上并没有告诉你它是否是一个终端,你仍然需要 isatty
为(这是一个周围的 的ioctl
了关于获取终端信息,至少在Linux上)。您可以添加以下上述程序(以的#include&LT一起; SYS / stat.h&GT;
)来获得什么样的文件标准输入的是额外的信息
If you want to distinguish between other cases (like a pipe, block special file, etc), you can use fstat
to extract some more file type information. Note that this doesn't actually tell you whether it's a terminal, you still need isatty
for that (which is a wrapper around an ioctl
that fetches information about a terminal, at least on Linux). You can add the following to the above program (along with #include <sys/stat.h>
) to get extra information about what kind of file stdin is.
if (fstat(STDIN_FILENO, &sb) == 0) {
if (S_ISBLK(sb.st_mode))
printf("stdin is a block special file\n");
else if (S_ISCHR(sb.st_mode))
printf("stdin is a character special file\n");
else if (S_ISDIR(sb.st_mode))
printf("stdin is a directory\n");
else if (S_ISFIFO(sb.st_mode))
printf("stdin is a FIFO (pipe)\n");
else if (S_ISREG(sb.st_mode))
printf("stdin is a regular file\n");
else if (S_ISLNK(sb.st_mode))
printf("stdin is a symlink\n");
else if (S_ISSOCK(sb.st_mode))
printf("stdin is a socket\n");
} else {
printf("failed to stat stdin\n");
}
请注意,你永远不会看到一个重定向符号链接,作为外壳将已经代表你的程序打开文件之前取消引用的符号链接;我不能让击是打开一个Unix域套接字。但是,所有的休息是可能的,其中,奇怪的是,一个目录。
Note that you will never see a symlink from a redirection, as the shell will have already dereferenced the symlink before opening the file on behalf of your program; and I couldn't get Bash to open a Unix domain socket either. But all of the rest are possible, including, surprisingly, a directory.
$ ./isatty
stdin is a tty
stdin is a character special file
$ ./isatty < ./isatty
stdin is not a tty
stdin is a regular file
$ sudo sh -c './isatty < /dev/sda'
stdin is not a tty
stdin is a block special file
$ sudo sh -c './isatty < /dev/console'
stdin is a tty
stdin is a character special file
$ cat isatty | ./isatty
stdin is not a tty
stdin is a FIFO (pipe)
$ mkfifo fifo
$ echo > fifo & # Need to do this or else opening the fifo for read will block
[1] 27931
$ ./isatty < fifo
stdin is not a tty
stdin is a FIFO (pipe)
[1]+ Done echo > fifo
$ ./isatty < .
stdin is not a tty
stdin is a directory
$ socat /dev/null UNIX-LISTEN:./unix-socket &
[1] 28044
$ ./isatty < ./unix-socket
bash: ./unix-socket: No such device or address
$ kill $!
[1]+ Exit 143 socat /dev/null UNIX-LISTEN:./unix-socket
$ ln -s isatty symlink
$ ./isatty < symlink
stdin is not a tty
stdin is a regular file
$ ln -s no-such-file broken-link
$ ./isatty < broken-link
bash: broken-link: No such file or directory
这篇关于如果输入重定向执行操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!