我的程序需要接受以下三种输入命令:
./Myprogram input.txt
./Myprogram < input.txt
./Myprogram
我正在考虑使用argc
来检查解决前两种情况的参数数量(因为重定向不算作参数)。但后来我坚持最后一个案例,它只是等待用户输入。
我想知道是否有办法判断shell命令中是否存在重定向?
对于更复杂的场景,例如重定向和argv形式的混合(见下文)。有没有办法做到这一点,或者只是一个糟糕的设计用于获取用户命令?
./Myprogram input1.txt input2.txt input3.txt
./Myprogram input1.txt < input2.txt input3.txt
./Myprogram
非常感谢任何帮助!
Z.Zen
答案 0 :(得分:6)
您的程序永远不会将重定向视为参数。所以在:
./Myprogram input.txt
./Myprogram < input.txt
./Myprogram
第二和第三种形式是相同的。至于你的第二套可能性:
./Myprogram input1.txt input2.txt input3.txt
./Myprogram input1.txt < input2.txt input3.txt
./Myprogram
第二行相当于:
./Myprogram input1.txt input3.txt < input2.txt
并且它与以下内容无法区分:
./Myprogram input1.txt input3.txt
(标准输入实际来自的唯一不同之处)。
某些程序处理来自stdin的混合输入和命令行中指定的文件的典型方式是接受"-"
作为特殊文件名,意思是“在此位置使用stdin作为输入文件在参数列表中“。如果参数列表为空,许多此类程序将默认处理单"-"
列表。
答案 1 :(得分:4)
基本算法是:
if (there are no arguments left after parsing options)
call_function(stdin);
else
{
foreach remaining argument
{
FILE *fp;
if (strcmp(argument, "-") == 0)
call_function(stdin);
else if ((fp = fopen(argument, "r")) == 0)
...error handling...
else
{
call_function(fp);
fclose(fp);
}
}
}
您也可以将文件名传递给'call_function()',有时我会使用指定的输出文件流编写代码。该函数('call_function()')处理一个文件 - 读取到文件末尾。它不会关闭文件;它被给了一个打开的文件,不应该关闭它。
当然,第一个'if'处理I / O重定向情况。
多年以后,我写了一个处理这个循环的函数。每当我需要在这个“UNIX过滤器”习语中编写命令时,它就简化了我的生活 - 这种情况经常发生。与标准化的错误报告包一起,它大大简化了生活。将它作为一个函数也允许我在其上使用变体,例如在覆盖之前创建文件备份的变体,或者如果函数成功完成则安全地覆盖文件。
答案 2 :(得分:1)
@R ..对于通常的情况是正确的。
如果您希望在#3情况下而不是#2中具有交互行为,除了让终端缓冲用户的输入行之外,您可以使用isatty
(具体为isatty(0)
)来确定是否存在一个人在另一端。
这不是标准C,但终端或shell的概念都不是!
答案 3 :(得分:0)
我想知道是否有办法判断shell命令中是否存在重定向?
没有。从你的程序的角度来看,这两种情况没有区别:
./Myprogram < input.txt
./Myprogram
在这两种情况下,程序都不接受任何命令行参数,并从标准输入中获取输入。
在第一种情况下,它是 shell 即将文件input.txt
的内容与程序的stdin
相关联,您的程序对此一无所知。
答案 4 :(得分:0)
可以通过在stdin上使用select()来判断是否要读取的数据。这不会告诉您是否存在重定向(您无法判断文件何时为空,或者由于某种原因,用户在您的程序有机会测试它之前设法将某些内容放在stdin上)。它是否适合你的情况取决于你想要在边缘情况下做什么。
或者,您可以在stdin上使用isatty()来查明它是否是tty。这是大多数程序要做的,以确定它们是否具有交互性,在您的情况下可能更好。
现在,您可能会注意到在第三种情况下阻止等待用户输入是所有标准工具的操作,并且可能是大多数用户对您的程序的期望。