我正在尝试将两个命令“合并”到一个(不存在的)命令中并将其通过管道传输。我的意思是...假设您有这两个命令: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
}
}
完整代码在这里:
最佳答案
您的方法确实有点过于复杂。这可以通过一个子进程和一个管道来实现(就像在原始 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/