【问题标题】:How to pass an extra option in ls using execv()?如何使用 execv() 在 ls 中传递一个额外的选项?
【发布时间】:2019-05-10 06:00:42
【问题描述】:

我正在尝试使用 execv() 函数执行这个简单的命令ls -1 *.c

#include<stdio.h>
#include<fcntl.h>
int main(int argc,char* argv[]){
char *arr[3]={"ls","-1","*.c"};
execv("/bin/ls",arr);
}

我得到的输出是

ls: cannot access *.c: No such file or directory

【问题讨论】:

  • char *arr[]={"ls","-1","*.c",NULL}; 指针数组需要一个NULL标记,这样才能确定它的长度。
  • * 这样的通配符由shell 解释,而不是ls
  • char *arr[]={"ls","-1","*.c",NULL}; 将给出相同的输出。
  • @user3133165 是的,但它不会因EFAULT 而崩溃或失败,甚至不会做更疯狂的事情。

标签: c linux wildcard


【解决方案1】:

您的代码中有一个大问题:execv 无法判断您传递的数组有多大。您绝对需要一个终止 NULL 元素来标记结束:

char *arr[] = { "ls", "-1", "*.c", NULL };

好的,现在我们有一个有效的execv 调用,我们可以处理ls 错误。

这样调用execv就相当于跑了

'ls' '-1' '*.c'

在命令行上(会产生同样的错误)。

当你这样做时

ls -1 *.c

在命令行中,ls 永远不会看到 *.c,因为 shell 会扩展通配符并将匹配的文件名列表传递给 ls

如果您想在您的 C 代码中复制它,您必须手动执行相同的操作。参见例如man glob 用于完成大部分工作的函数。这是手册页中的一个改编示例,显示了一般原则:

glob_t globbuf;

globbuf.gl_offs = 2;
glob("*.c", GLOB_DOOFFS, NULL, &globbuf);
globbuf.gl_pathv[0] = "ls";
globbuf.gl_pathv[1] = "-1";
execv("/bin/ls", globbuf.gl_pathv);

【讨论】:

  • 之后是否需要使用globfree(&amp;globbuf); 释放 globbuf 中分配的缓冲区?
  • @TomKuschel 如果execv成功,就没有后续了。
  • 为什么我需要ls 作为参数?它不是已经存在于带有execv("/bin/ls", globbuf.gl_pathv) 的命令中了吗?那不就是编译成/bin/ls ls -l *.c吗(*.c被替换成globbuf的文件列表)。
  • @TomKuschel /bin/ls 是要运行的可执行文件。按照惯例,程序希望在argv[0](第一个参数)中有自己的名称。
猜你喜欢
  • 1970-01-01
  • 2015-04-14
  • 1970-01-01
  • 1970-01-01
  • 2011-06-02
  • 2019-07-11
  • 2015-03-10
  • 2013-07-21
  • 1970-01-01
相关资源
最近更新 更多