【问题标题】:Combining two commands with a pipe用管道组合两个命令
【发布时间】:2016-08-22 05:10:27
【问题描述】:

我正在尝试将两个命令“合并”到一个(不存在的)命令中并通过管道传输它。我的意思是……假设您有这两个命令: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 | wc -l ; } &lt; file.txt &gt; out.txt。输入重定向适用于管道中的第一个命令,输出适用于最后一个命令。

标签: c bash pipe fork


【解决方案1】:

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

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

这个

  • 创建管道
  • 分叉两个进程
  • 让 grep 写入管道
  • 让 wc 从管道中读取

但是只分叉一个进程就足够了,因为我们不需要返回父进程。这将产生以下代码:

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

只有当execlp() 之一失败时,才会到达exit()

【讨论】:

  • 我明白你做了什么,但我想只在子进程上执行命令。
  • @snobis 好吧,那么你只需要为 grep 进程再分叉一次。
猜你喜欢
  • 2017-06-03
  • 1970-01-01
  • 1970-01-01
  • 2019-07-28
  • 2014-08-13
  • 1970-01-01
  • 2014-08-15
  • 1970-01-01
  • 2016-11-11
相关资源
最近更新 更多