当前位置: 首页 > news >正文

C语言程序实现shell命令的重定向符号功能

在 Linux 中,Shell 的重定向符号(如 ><>> 等)用于将命令的输入或输出重定向到文件或其他流。我们可以用 C 语言实现类似的功能,通过使用系统调用(如 dup2open 等)来重定向标准输入(stdin)、标准输出(stdout)和标准错误(stderr)。

以下是一个简单的 C 语言程序,实现了类似 Shell 的重定向功能:

功能:

  1. 支持输出重定向(>):将命令的输出写入文件。

  2. 支持追加输出重定向(>>):将命令的输出追加到文件末尾。

  3. 支持输入重定向(<):从文件中读取输入。


代码实现:

#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;
}

代码说明:

  1. parse_command 函数

    • 解析命令行参数,提取命令、输入文件和输出文件。

    • 支持 <> 和 >> 重定向符号。

  2. execute_command 函数

    • 使用 open 打开文件,并通过 dup2 将文件描述符重定向到标准输入或输出。

    • 使用 execvp 执行命令。

  3. main 函数

    • 解析命令行参数。

    • 创建子进程执行命令,父进程等待子进程完成。


编译和运行:

  1. 将代码保存为 redirect.c

  2. 使用以下命令编译:

    gcc -o redirect redirect.c

  3. 运行程序并测试重定向功能:

    • 输入重定向:

      ./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

注意事项:

  1. 程序仅支持简单的重定向功能,不支持管道(|)或其他复杂功能。

  2. 如果命令不存在或文件无法打开,程序会报错并退出。

相关文章:

  • D-FINE模型详解及代码复现
  • 酒店旅游API:数据交互的隐形桥梁——以携程API为例
  • Jenkins 视图(View)
  • 蓝桥杯15 填空题
  • TensorFlow v2.16 Overview
  • JDK源码系列(一)Object
  • Kubernetes控制平面组件:APIServer 基于 引导Token 的认证机制
  • C#上位机--选择语句(switch)
  • Typora软件(Markdown编辑器)详细安装教程(附补丁包)2025最详细图文教程安装手册
  • 打开Firefox自动打开hao360.hjttif.com标签解决方案
  • Resource not found: roslaunchROS path [0]=/opt/ros/noetic/share/ros
  • DeepSeek模型量化
  • 第一个CMAKE项目hello cmake
  • C++ 设计模式-解释器模式
  • Vue2 和 Vue3 的区别
  • 高级推理的多样化推理与验证
  • 前端(AJAX)学习笔记(CLASS 3):AJAX原理
  • 2025年度福建省职业院校技能大赛中职组“网络建设与运维”赛项规程模块三
  • 从Revit建模软件的“编辑”操作分析:构件与编辑 = 数据结构与算法
  • 【排版教程】如何在Word/WPS中优雅的插入参考文献
  • 陈龙带你观察上海生物多样性,纪录片《我的城市邻居》明播出
  • 国家统计局:消费对我国经济增长的拉动有望持续增长
  • 北斗系统全面进入11个国际组织的标准体系
  • 特写|银耳种植“北移”到沧州盐山,村民入伙可年增收4万元
  • 有关“普泽会”,俄官方表示:有可能
  • 广西壮族自治区党委常委会:坚决拥护党中央对蓝天立进行审查调查的决定