将标准输出重定向到文件

问题描述 投票:0回答:3

我正在尝试在 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;
}

注释行指的是我认为重定向所需的那些操作。 我应该更改什么以将 ls 的输出重定向到 foo.txt?

c redirect pipe posix
3个回答
24
投票

在处理将输出重定向到文件时,您可以使用 freopen()。

假设您正在尝试将您的

stdout
重定向到文件'output.txt'然后你可以写-

freopen("output.txt", "a+", stdout); 

此处为附加模式的“

a+
”。如果文件存在,则文件以追加模式打开。否则会创建一个新文件。

stdout
重新打开
freopen()
后,所有输出语句(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
”。


16
投票

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

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

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;

但是,您也可以按照其他答案的建议使用 freopen。

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

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

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

  • dup2()可以用来代替dup();否则,如果标准输入未打开,代码将失败,因为它复制到第一个可用的文件描述符。

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

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


0
投票

“在 ubuntu 中使用终端测试”.

例如你的代码是“mike.c” 你首先编译它

gcc mike.c

如果没有错误, 你然后做

./a.out > file

您将在与 mike.c 相同的目录(文件夹)中找到包含代码的文件

注意文件可以是 (file.txt, file.md ...)

希望这有帮助。

© www.soinside.com 2019 - 2024. All rights reserved.