将两个命令与管道组合

标签 c bash pipe fork

我正在尝试将两个命令“合并”到一个(不存在的)命令中并将其通过管道传输。我的意思是...假设您有这两个命令:grep text < file.txt | wc -l > out.txt ,可以表示这两个命令的(不存在的)命令可能类似于 (grepwc -l < file.txt)然后将行数输出到 out.txt 中。基本上这些 (grepwc) 命令应该具有与 grep text < file.txt | wc -l > out.txt 相同的行为。但更短。

我尝试过类似的方法,但我认为我的方法离实现目标还很远。我使用一个名为 commlist 的结构,其中包含已由 cmd、argc 和 argv 解析的命令。 inputfile 和 outputfile 是 open() 中使用的文件的路径名。

我正在使用的结构。

typedef struct command {
char *cmd;              
int argc;               
char *argv[MAXARGS+1];  
struct command *next;
} COMMAND;

和代码:

void execute(COMMAND *commlist) {
  int fd[2];
  pid_t pid;
  int n_pipes=2; //pipes needed
  COMMAND *aux = commlist;

  int i;
  for(i=0;i<n_pipes; i++){
    int oldfd = 0;

    if(fd[0]!=0){
      close(fd[1]);
      oldfd = fd[0];
    }
      pipe(fd);

      if((pid=fork())<0){perror("Fork Failed");}
      else 
        if(pid == 0){

          if(inputfile!=NULL){
            int in = open(inputfile,O_RDONLY);
            dup2(in,STDIN_FILENO);
            inputfile = NULL;
          }

          if(outputfile != NULL){
            int out = open(outputfile, O_RDWR |O_CREAT | O_TRUNC, S_IRWXU);
            dup2(out,STDOUT_FILENO);
            outputfile = NULL;
          }

          if(oldfd)
            dup2(oldfd,STDIN_FILENO);

          if(commlist->cmd == "grepwc"){
            if(i==0){
              if(execlp("grep","grep","celio",NULL)<0){
                perror("Bad command");
                exit(1);    
              }
            }

            if(i==1){
              if(execlp("wc","wc","-l",NULL) < 0){
                perror("Bad command");
                exit(1);
              }
            }
          }
        }//child
  }
}

完整代码在这里:

http://pastebin.com/tYGWwUjS

http://pastebin.com/sNJhEg2Y

最佳答案

您的方法确实有点过于复杂。这可以通过一个子进程和一个管道来实现(就像在原始 shell 命令中一样)。让我们看一下:

grep text < file.txt | wc -l > out.txt

这个

  • 创建一个管道
  • fork 两个进程
  • 让 grep 写入管道
  • 让wc从管道读取

但是只fork一个进程就够了,因为我们不需要返回到父进程。这导致以下代码:

#include <stdlib.h>
#include <unistd.h>

int main (void) {
    int fd[2];

    pipe(fd);

    if (fork()) {
        // Child process
        dup2(fd[0], 0); // wc reads from the pipe
        close(fd[0]);
        close(fd[1]);
        execlp("wc", "wc", "-l", NULL);
    } else {
        // Parent process
        dup2(fd[1], 1); // grep writes to the pipe
        close(fd[0]);
        close(fd[1]);
        execlp("grep", "grep", "celio", NULL);
    }
    exit(EXIT_FAILURE);
}

exit() 只有在其中一个 execlp() 失败时才会到达。

关于将两个命令与管道组合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36897690/

相关文章:

c - 结构体数组的内存分配问题?

node.js - Bower:安装后 "command not found"

linux - 如何 gzip 文件同时将压缩内容打印到标准输出

java - 多个线程与管道流通信并使用 PushbackInputStream

c - 在C中添加随机字符

c - c 中的 pragma omp 快捷方式

c - 用C创建外壳。如何实现输入和输出重定向?

bash - bash 脚本中要 curl 的变量中的特殊字符

c++ - 是否可以使用 C++ 流类来缓冲从管道读取的数据?