execvp命令未运行ls -l * .c

时间:2020-04-03 09:39:04

标签: c unix system system-calls systems-programming

我的execvp未运行ls -l *.c命令。我尝试使用两种方法:

  1. 一个带有我的ls所在的文件路径的文件位于\bin\ls中。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(void)
{
    char *cmdargs[] = { "ls", "-l", "*.c", NULL };
    pid_t pid;
    pid = fork();
    if (pid == 0)
        execvp("\bin\ls", cmdargs);
    else
    {
        wait(NULL);
        printf("Child terminates\n");
    }
    return 0;
}

输出:

ls: *.c: No such file or directory
Child terminates
  1. 我使用的第二种方法是添加cmdargs[0]而不是文件路径。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(void)
{
    char *cmdargs[] = { "ls", "-l", "*.c", NULL };
    pid_t pid;
    pid = fork();
    if (pid == 0)
        execvp(cmdargs[0], cmdargs);
    else
    {
        wait(NULL);
        printf("Child terminates\n");
    }
    return 0;
}

输出:

ls: *.c: No such file or directory
Child terminates

当我只运行命令ls -l *.c时,它的确显示了所有以.c结尾的文件。 Execvp没有显示文件。有一个与此相关的问题,但这并没有帮助我。

4 个答案:

答案 0 :(得分:1)

GLOB模式是由Shell而不是ls本身扩展的。 您可以通过exec创建子外壳来实现所需的功能。 这是一个示例:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

int main() {
    char *cmdargs[] = { "sh", "-c", "ls -l *.c", NULL };

    pid_t pid;
    pid = fork();
    if (pid == 0) {
        execvp(cmdargs[0], cmdargs);
    } else {
        wait(NULL);
        printf("Child terminates\n");
    }

    return 0;
}

如果需要,您也可以雇用system(3)

答案 1 :(得分:0)

星号模式foreach($xml->children() as $videos) { $id = $videos->nodeValue; //It doesn't work echo "Idas: ".$id." </br>"; $title = $videos->title; } 由外壳执行,但由*进行。

例如,您可以将lsexec一起使用。

编辑OP的回复, 无需在字符串数组中使用sh即可获取所有文件,并根据需要过滤字符串。

答案 2 :(得分:0)

输入ls -l *.c时,shell将解析该命令,找到glob模式并将其展开。然后它将使用扩展的参数列表调用ls,并使用execvp之类的数组调用{"ls", "-l", "a.c", "b.c", "c.c", NULL}lsexecvp都不会自行扩展glob,而是由外壳程序来完成的。

因此,如果要使用glob,则可以选择自己扩展它们(通过手动浏览当前目录并将以.c结尾的所有文件添加到数组中,或使用POSIX glob函数) ),或者通过外壳。您可以通过使用{"sh", "-c", "ls -l *.c", NULL}作为传递给execvp的数组(或类似地,但不使用数组,使用execl等)显式调用来完成后者,也可以使用{ {1}},它总是穿过外壳。

请注意,如果参数包含不受信任的用户输入,则您绝对不希望通过shell,因此在这种情况下,您自己/使用system("ls -l *.c")扩展glob是可行的方法。 / p>

答案 3 :(得分:0)

或者调用shell将*.c全局模式扩展到文件,您可以使用glob扩展*.c自己列出文件,然后构造一个动态分配的参数数组

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <glob.h>
#include <stdlib.h>

int main() {
    glob_t result = {0};
    int err = glob("*.c", GLOB_ERR, NULL, &result);
    if (err) return err;
    char **cmdargs = malloc((2 + result.gl_pathc + 1) * sizeof(cmdargs));
    if (cmdargs == NULL) return EXIT_FAILURE;
    cmdargs[0] = "ls";
    cmdargs[1] = "-l";
    for (size_t i = 0; i < result.gl_pathc; ++i) {
        cmdargs[i + 2] = result.gl_pathv[i];
    }
    cmdargs[2 + result.gl_pathc] = NULL;

    pid_t pid = fork();
    if (pid == 0) {
        execvp(cmdargs[0], cmdargs);
    } else {
        wait(NULL);
        printf("Child terminates\n");
    }
    globfree(&result);
    return 0;
}