繁体   English   中英

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

[英]execvp command not running ls -l *.c

我的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;
}

Output:

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

Output:

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

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

GLOB 模式由 shell 扩展,而不是ls本身。 您可以通过 exec 创建一个子 shell 来实现您想要的。 这是一个例子:

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

星号模式*由 shell 进行,但由ls进行。

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

编辑 OP 的响应,获取所有文件而不使用字符串数组中的*.c并根据需要过滤字符串。

当您输入ls -l *.c时,shell 将解析该命令,找到 glob 模式并将其展开。 然后它将使用扩展的参数列表调用ls ,使用像{"ls", "-l", "ac", "bc", "cc", NULL}这样的数组调用execvp lsexecvp都不会自行扩展 glob,它是 shell 做到的。

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

Note that you definitely don't want to go through the shell if the arguments contain untrusted user input, so in that case expanding the glob(s) yourself / using glob would be the way to go.

Alternatively to invoking the shell to expand the *.c glob pattern to files, you can use glob to expand *.c to list of files yourself and then construct a dynamically allocated array of arguments.

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM