将标准输出重定向到文件
Redirect stdout to a file
我正在尝试在 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?
在处理将输出重定向到文件时,您可以使用 freopen().
假设您正在尝试将 stdout
重定向到文件“output.txt”,那么您可以写-
freopen("output.txt", "a+", stdout);
此处“a+
”表示追加模式。如果文件存在,则文件以追加模式打开。否则会创建一个新文件。
使用 freopen()
重新打开 stdout
后,所有输出语句(printf、putchar)都重定向到 'output.txt'。因此,之后任何 printf()
语句都会将其输出重定向到 'output.txt' 文件。
如果您想再次恢复 printf()
的默认行为(即在 terminal/command 提示符下打印),那么您必须使用以下代码再次重新分配 stdout
-
freopen("/dev/tty", "w", stdout); /*for gcc, ubuntu*/
或者 -
freopen("CON", "w", stdout); /*Mingw C++; Windows*/
但是类似的技术适用于“stdin
”。
你的代码基本上做的是你打开一个管道,然后分叉进程并在子进程中(在注释代码中)关闭标准输出,将管道复制到标准输出并执行和 ls 命令,然后(在非-注释代码)向管道写入 4 个字节。在父进程中,你从管道中读取数据,等待子进程完成。
现在您想将标准输出重定向到一个文件。您可以通过使用 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) 中止,则重试系统调用。
我正在尝试在 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?
在处理将输出重定向到文件时,您可以使用 freopen().
假设您正在尝试将 stdout
重定向到文件“output.txt”,那么您可以写-
freopen("output.txt", "a+", stdout);
此处“a+
”表示追加模式。如果文件存在,则文件以追加模式打开。否则会创建一个新文件。
使用 freopen()
重新打开 stdout
后,所有输出语句(printf、putchar)都重定向到 'output.txt'。因此,之后任何 printf()
语句都会将其输出重定向到 'output.txt' 文件。
如果您想再次恢复 printf()
的默认行为(即在 terminal/command 提示符下打印),那么您必须使用以下代码再次重新分配 stdout
-
freopen("/dev/tty", "w", stdout); /*for gcc, ubuntu*/
或者 -
freopen("CON", "w", stdout); /*Mingw C++; Windows*/
但是类似的技术适用于“stdin
”。
你的代码基本上做的是你打开一个管道,然后分叉进程并在子进程中(在注释代码中)关闭标准输出,将管道复制到标准输出并执行和 ls 命令,然后(在非-注释代码)向管道写入 4 个字节。在父进程中,你从管道中读取数据,等待子进程完成。
现在您想将标准输出重定向到一个文件。您可以通过使用 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) 中止,则重试系统调用。