C 将标准输出重定向到文件

C 将标准输出重定向到文件,c,redirect,pipe,posix,C,Redirect,Pipe,Posix,我正在尝试在C中执行bash命令ls>foo.txt 下面的代码将输出重定向到变量 #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <unistd.h> #include <sys/wait.h> int main(){ int pfds[2]; char buf[30]; pipe(pfds); if (!fork())

我正在尝试在C中执行bash命令
ls>foo.txt

下面的代码将输出重定向到变量

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>

int main(){
  int pfds[2];
  char buf[30];

  pipe(pfds);

  if (!fork()) {
    close(pfds[0]);
     //close(1);//Close stdout
    //dup(pfds[1]);
    //execlp("ls", "ls", NULL);
    write(pfds[1], "test", 5); //Writing in the pipe
    exit(0);
  } else {
    close(pfds[1]);  
    read(pfds[0], buf, 5); //Read from pipe
    wait(NULL);
  }
  return 0;
}
#包括
#包括
#包括
#包括
#包括
int main(){
int-pfds[2];
char-buf[30];
管道(pfds);
如果(!fork()){
关闭(pfds[0]);
//关闭(1);//关闭标准输出
//dup(pfds[1]);
//execlp(“ls”、“ls”、NULL);
写入(pfds[1],“test”,5);//在管道中写入
出口(0);
}否则{
关闭(pfds[1]);
读取(pfds[0],buf,5);//从管道读取
等待(空);
}
返回0;
}
注释行是指我认为重定向所需的那些操作。
在处理将输出重定向到您可能使用的文件时,我应该更改什么以将ls的输出重定向到foo.txt?

假设您正试图将
stdout
重定向到文件“output.txt”,则可以编写-

freopen("output.txt", "a+", stdout); 
此处“
a+
”用于附加模式。如果文件存在,则文件将以追加模式打开。否则将创建一个新文件

使用
freopen()
重新打开
stdout
后,所有输出语句(printf、putchar)都被重定向到“output.txt”。因此在此之后,任何
printf()
语句都会将其输出重定向到'output.txt'文件

如果要再次恢复
printf()
的默认行为(即在终端/命令提示符下打印),则必须使用以下代码再次重新分配
stdout
-

freopen("/dev/tty", "w", stdout); /*for gcc, ubuntu*/  

freopen("CON", "w", stdout); /*Mingw C++; Windows*/ 

然而,类似的技术适用于“
stdin

您的代码基本上是打开一个管道,然后分叉进程,在子进程中(在注释代码中)关闭stdout,将管道复制到stdout并执行和ls命令,然后(在非注释代码中)向管道写入4个字节。在父进程中,从管道读取数据并等待子进程完成

现在要将标准输出重定向到文件。您可以通过使用open()系统调用打开一个文件,然后将该文件描述符复制到stdout来实现这一点。类似于(我还没有测试过,所以要小心代码中的bug):

但是,您也可以按照另一个答案的建议使用freopen

但是,我对您的代码和修改后的代码有几点担心:

  • pipe()和open()系统调用可能会失败。您应该始终检查系统调用故障

  • fork()系统调用可能会失败。同上

  • 可以使用dup2()代替dup();否则,如果stdin没有打开,代码将失败,因为它复制到第一个可用的文件描述符

  • execlp()系统调用可能失败。同上

  • 我认为wait()可以被信号(EINTR)中断。建议将其包装在一个包装器上,如果系统调用被信号中止(errno==EINTR),该包装器将重试系统调用


为什么在模拟的shell语法中没有显示管道的情况下创建管道?“相当于C中的[此bash代码]”并没有让它成为bash问题。如果你想让bash(而不是C!)方面的专家来看看它,那么只需将它标记为bash。我正在Linux和FreeBSD上使用
fork()
生成一个进程来测试它,并且创建了
output.txt
文件,但没有收到任何文本。这在这些情况下有效吗?或者可能在派生的进程上没有
stdout
流?也许需要某种重定向?
int filefd = open("foo.txt", O_WRONLY|O_CREAT, 0666);
if (!fork()) {
  close(1);//Close stdout
  dup(filefd);
  execlp("ls", "ls", NULL);
} else {
  close(filefd);
  wait(NULL);
}
return 0;