C语言程序实现shell命令的重定向符号功能
在 Linux 中,Shell 的重定向符号(如 >
、<
、>>
等)用于将命令的输入或输出重定向到文件或其他流。我们可以用 C 语言实现类似的功能,通过使用系统调用(如 dup2
、open
等)来重定向标准输入(stdin
)、标准输出(stdout
)和标准错误(stderr
)。
以下是一个简单的 C 语言程序,实现了类似 Shell 的重定向功能:
功能:
-
支持输出重定向(
>
):将命令的输出写入文件。 -
支持追加输出重定向(
>>
):将命令的输出追加到文件末尾。 -
支持输入重定向(
<
):从文件中读取输入。
代码实现:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/wait.h>
// 解析命令和重定向符号
void parse_command(char *command, char **args, char *input_file, char *output_file, int *append) {
char *token;
int i = 0;
// 解析命令和参数
token = strtok(command, " ");
while (token != NULL) {
if (strcmp(token, "<") == 0) {
// 输入重定向
token = strtok(NULL, " ");
strcpy(input_file, token);
} else if (strcmp(token, ">") == 0) {
// 输出重定向(覆盖)
token = strtok(NULL, " ");
strcpy(output_file, token);
} else if (strcmp(token, ">>") == 0) {
// 输出重定向(追加)
token = strtok(NULL, " ");
strcpy(output_file, token);
*append = 1;
} else {
// 命令参数
args[i++] = token;
}
token = strtok(NULL, " ");
}
args[i] = NULL; // 参数列表以 NULL 结尾
}
// 执行命令并处理重定向
void execute_command(char **args, char *input_file, char *output_file, int append) {
int input_fd, output_fd;
// 输入重定向
if (input_file[0] != '\0') {
input_fd = open(input_file, O_RDONLY);
if (input_fd < 0) {
perror("Error opening input file");
exit(EXIT_FAILURE);
}
dup2(input_fd, STDIN_FILENO); // 将文件描述符重定向到标准输入
close(input_fd);
}
// 输出重定向
if (output_file[0] != '\0') {
int flags = O_WRONLY | O_CREAT;
if (append) {
flags |= O_APPEND; // 追加模式
} else {
flags |= O_TRUNC; // 覆盖模式
}
output_fd = open(output_file, flags, 0644);
if (output_fd < 0) {
perror("Error opening output file");
exit(EXIT_FAILURE);
}
dup2(output_fd, STDOUT_FILENO); // 将文件描述符重定向到标准输出
close(output_fd);
}
// 执行命令
if (execvp(args[0], args) < 0) {
perror("Error executing command");
exit(EXIT_FAILURE);
}
}
int main(int argc, char *argv[]) {
if (argc < 2) {
fprintf(stderr, "Usage: %s <command> [args] [< input_file] [> output_file] [>> output_file]\n", argv[0]);
return EXIT_FAILURE;
}
char command[1024];
char *args[64];
char input_file[256] = "";
char output_file[256] = "";
int append = 0;
// 将命令行参数拼接为字符串
strcpy(command, argv[1]);
for (int i = 2; i < argc; i++) {
strcat(command, " ");
strcat(command, argv[i]);
}
// 解析命令和重定向符号
parse_command(command, args, input_file, output_file, &append);
// 创建子进程执行命令
pid_t pid = fork();
if (pid < 0) {
perror("Error forking process");
return EXIT_FAILURE;
} else if (pid == 0) {
// 子进程
execute_command(args, input_file, output_file, append);
} else {
// 父进程等待子进程完成
wait(NULL);
}
return EXIT_SUCCESS;
}
代码说明:
-
parse_command
函数:-
解析命令行参数,提取命令、输入文件和输出文件。
-
支持
<
、>
和>>
重定向符号。
-
-
execute_command
函数:-
使用
open
打开文件,并通过dup2
将文件描述符重定向到标准输入或输出。 -
使用
execvp
执行命令。
-
-
main
函数:-
解析命令行参数。
-
创建子进程执行命令,父进程等待子进程完成。
-
编译和运行:
-
将代码保存为
redirect.c
。 -
使用以下命令编译:
gcc -o redirect redirect.c
-
运行程序并测试重定向功能:
-
输入重定向:
./redirect "wc -l" < input.txt
-
输出重定向(覆盖):
./redirect "ls -l" > output.txt
-
输出重定向(追加):
./redirect "echo Hello" >> output.txt
-
示例:
假设有一个文件 input.txt
,内容如下:
line1
line2
line3
运行以下命令:
./redirect "wc -l" < input.txt > output.txt
output.txt
的内容将是:
3
注意事项:
-
程序仅支持简单的重定向功能,不支持管道(
|
)或其他复杂功能。 -
如果命令不存在或文件无法打开,程序会报错并退出。