简体   繁体   English

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

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

My execvp is not running ls -l *.c command.我的execvp没有运行ls -l *.c命令。 I have tried to use two methods:我尝试使用两种方法:

  1. One with the file path where my ls is located which is in \bin\ls .我的 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: Output:

ls: *.c: No such file or directory
Child terminates
  1. The second method I used was to add cmdargs[0] instead of the file path.我使用的第二种方法是添加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: Output:

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

When I just run the command ls -l *.c , it does show me all the files which end with .c .当我只运行命令ls -l *.c时,它会显示所有以.c结尾的文件。 Execvp does not show me the files. Execvp 没有向我显示文件。 There was a question related to this but that did not help me.有一个与此相关的问题,但这对我没有帮助。

GLOB pattern is expanded by shell, not the ls itself. GLOB 模式由 shell 扩展,而不是ls本身。 You may achieve what you want by creating a subshell via exec.您可以通过 exec 创建一个子 shell 来实现您想要的。 Here's an example of that:这是一个例子:

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

You may also employ system(3) for this if you want.如果需要,您也可以为此使用system(3)

The asterisk pattern * is carried on by the shell, but by the ls .星号模式*由 shell 进行,但由ls进行。

You can use exec with sh , for example.例如,您可以将execsh一起使用。

Editing over the OP's response, Obtain all files without using *.c in a string array and filter the strings as you wish.编辑 OP 的响应,获取所有文件而不使用字符串数组中的*.c并根据需要过滤字符串。

When you enter ls -l *.c , the shell will parse that command, find the glob pattern and expand it.当您输入ls -l *.c时,shell 将解析该命令,找到 glob 模式并将其展开。 It will then call ls with the expanded argument list, calling execvp with an array like {"ls", "-l", "ac", "bc", "cc", NULL} .然后它将使用扩展的参数列表调用ls ,使用像{"ls", "-l", "ac", "bc", "cc", NULL}这样的数组调用execvp Neither ls nor the execvp expand globs by themselves, it's the shell that does it. lsexecvp都不会自行扩展 glob,它是 shell 做到的。

So if you want to use globs, your options are to either expand them yourself (either by manually going through the current directory and adding all files that end with .c to your array or by using the POSIX glob function), or to go through the shell.因此,如果您想使用 glob,您的选择是自己扩展它们(通过手动浏览当前目录并将所有以.c结尾的文件添加到您的数组或使用 POSIX glob 函数),或者通过 go shell。 You can do the latter either by explicitly invoking by using {"sh", "-c", "ls -l *.c", NULL} as the array you pass to execvp (or similarly, but without the array, using execl etc.) or you could use system("ls -l *.c") , which always goes through the 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. 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. 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