簡體   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