2014-01-26 32 views
2

这是我正在做的一组练习中的一个步骤。我写的程序应该有两个以上的参数。第一个参数的使用尚未实现。剩下的参数是一个目录列表。用叉子execvp pipe和dup2的猫

在这一步中,我要做的是为参数中给出的每个目录创建一个cat实例,使用cat获取每个目录的所有文件的内容并打印内容。我应该能够处理/ home /目录和/ home /目录/这两个路径(最后一个或没有)

目前我正在做的是试图运行cat /参数/ home/directory/*这样它将读取给定目录中的所有文件并返回它们的内容。这是我的代码:

#include "Step1.h" 

int main(int argc,char* argv[]) 
{ 
    if(argc < 3) 
    { 
     printf("Usage: ./Step1 <exclusions file> <folder1> <folder2> <folder3> ...\n"); 
     return -1; 
    } 

    int i; 
    for(i=2; i<argc; i++) 
    { 
     int catpipe[2]; 
     if(pipe(catpipe)) 
     { 
      printf("Error in pipe\n"); 
      return -1; 
     } 
     pid_t pid = fork(); 
     if(pid < 0) 
     { 
      printf("Error in fork\n"); 
      return -1; 
     } 
     if(!pid) 
     { 
      dup2(catpipe[1],1); // cat pipe is used to get the output of cat program into this program. 
      close(catpipe[1]); 
      close(catpipe[0]); 
      char* args[3]; 
      args[0] = "/bin/cat"; 
      int length = strlen(argv[i]); 
      char* path; 
      if(argv[i][length - 1] != '/') // the path given does not have the ending/
      { 
       path = malloc(length + 3); 
       strcpy(path,argv[i]); 
       path[length] = '/';  //append/at the end 
       path[length+1] = '*'; // append * at the end 
       path[length+2] = '\0'; 
      } 
      else 
      { 
       path = malloc(length + 2); // the path contains the ending/
       strcpy(path,argv[i]); 
       path[length] = '*';  // append * at the end 
       path[length+1] = '\0'; 
      }     
      args[1] = path; 
      args[2] = NULL; 
      printf("%s\n",path); 
      execvp("/bin/cat",args); 
     } 
     close(catpipe[1]); 
     char buffer[200]; 
     int total = read(catpipe[0],buffer,200); // read the output of cat program and print it. 
     buffer[total]='\0'; 
     printf("The buffer contains: %s\n",buffer); 
    } 
    return 0; 
} 

我跑这个代码如下:

[email protected]:~/project$ ./Step1 exclusions ./testdirectory1 ./testdirectory2/ 

和我得到的结果是:

/bin/cat: ./testdirectory1/*: No such file or directory 
The buffer contains: 
The buffer contains: ./testdirectory2/* 

[email protected]:~/project$ /bin/cat: ./testdirectory2/*: No such file or directory 

[email protected]:~/project$ 

但是当我做:

[email protected]:~/project$ /bin/cat ./testdirectory1/* 

结果是:

Testline 1 of testfile1 in testdirectory1 
Test line 1 of testfile1 in testdirectory1 
Testline 1 of testfile2 in testdirectory1 
Testline 1 of testfile3 in testdirectory1 

请帮我拿这个结果与我的程序。

在此先感谢

+0

这是因为当你在shell中测试时,参数中的'*'被shell扩展,而当你做一个fork时,'*'被解释为是,只是一个文件,其名称是'*' – zmo

+0

@zmo是否无法解决此问题? – HZero

+0

看到我的答案;-) – zmo

回答

0

所以基本上你错在你的代码是什么,你认为如果你给/directory/*作为参数传递给catcat将扩大为“多文件”,而cat了解您想要打开一个名为*的文件。

扩展*的简单方法是通过shell调用cat,该shell将从*扩展为“多个文件”。

要实现的话,你可以取代你的execvp()system(…)通话,这基本上是execl("sh", "sh", "-c", …, NULL)这里......是你的命令(例如,你可以简单地调用"/bin/sh", "-c", "/bin/cat", "/directory/*")*应该由外壳扩展。

或者你可以使用你自己的递归目录遍历算法,比如that one

+0

谢谢。我被指示使用glob()或wordexp()。这样做有什么不利吗? – HZero

0

我想我想出了自己的问题的答案,我发布了这个信息,认为像我这样的人有一天会觉得它有用,但是我对C还不是很擅长,所以如果这个答案是错误的,或者是有一些错误/弱点的话在这里,请随时纠正它。

我的答案的关键是使用函数wordexp()。它可以用来扩展给定的路径:代字符,正则表达式,变量和全部。所以这是我的答案:

#include "Step1.h" 

int main(int argc,char* argv[]) 
{ 
    if(argc < 3) 
    { 
     printf("Usage: ./Step1 <exclusions file> <folder1> <folder2> <folder3> ...\n"); 
     return -1; 
    } 

    int i; 
    for(i=2; i<argc; i++) 
    { 
     int catpipe[2]; 
     if(pipe(catpipe)) 
     { 
      printf("Error in pipe\n"); 
      return -1; 
     } 
     pid_t pid = fork(); 
     if(pid < 0) 
     { 
      printf("Error in fork\n"); 
      return -1; 
     } 
     if(!pid) 
     { 
      dup2(catpipe[1],1); // cat pipe is used to get the output of cat program into this program. 
      close(catpipe[1]); 
      close(catpipe[0]); 

      int length = strlen(argv[i]); 
      char* path; 
      if(argv[i][length - 1] != '/') // the path given does not have the ending/
      { 
       path = malloc(length + 3); 
       strcpy(path,argv[i]); 
       path[length] = '/';  //append/at the end 
       path[length+1] = '*'; // append * at the end 
       path[length+2] = '\0'; 
      } 
      else 
      { 
       path = malloc(length + 2); // the path contains the ending/
       strcpy(path,argv[i]); 
       path[length] = '*';  // append * at the end 
       path[length+1] = '\0'; 
      }    

     wordexp_t p; 
     char **w; 
      wordexp(path, &p, 0); 
     char** args = malloc((p.we_wordc + 2) * sizeof(char*)); 
      args[0] = "/bin/cat"; 
     w = p.we_wordv; 
     int j; 
     for (j = 0; j < p.we_wordc; j++) 
     args[j+1] = w[j];     
      args[p.we_wordc + 1] = NULL; 

      execvp("/bin/cat",args); 
     } 
     close(catpipe[1]); 
     char buffer[1024]; 
     int total = read(catpipe[0],buffer,1024); // read the output of cat program and print it. 
     buffer[total]='\0'; 
     printf("The buffer contains: %s\n",buffer); 
    } 
    return 0; 
} 
+0

如果您决定自己扩展shell元字符,那么您已经以正确的方式去完成这项工作。更简单的选择是使用shell来执行shell元字符扩展;你调用'sh -c“cat $ directory/*”',意识到实际上并不需要双引号,并且使用你给出的参数来代替'$ directory'。一般来说,你需要一个循环来读取响应,而不是一次调用'read()'。 –