команда execvp не выполняется ls -l *. c - PullRequest
0 голосов
/ 03 апреля 2020

Мой 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
Второй метод, который я использовал, был добавить 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 ]

1 голос
/ 03 апреля 2020
Шаблон

GLOB расширяется оболочкой, а не самой ls. Вы можете достичь того, чего хотите, создавая подоболочку через exe c. Вот пример этого:

#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) для этого, если хотите.

0 голосов
/ 03 апреля 2020

Кроме того, чтобы вызвать оболочку для развертывания шаблона глобуса *.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;
}
0 голосов
/ 03 апреля 2020

Когда вы введете ls -l *.c, оболочка проанализирует эту команду, найдет шаблон глобуса и развернет его. Затем он вызовет ls с расширенным списком аргументов, вызовет execvp с массивом, подобным {"ls", "-l", "a.c", "b.c", "c.c", NULL}. Ни ls, ни execvp сами по себе не расширяют глобусы, это делает оболочка.

Так что, если вы хотите использовать глобусы, вы можете либо расширить их самостоятельно (либо вручную выполнить текущий каталог и добавление всех файлов, которые заканчиваются на .c, в ваш массив или с помощью функции glob POSIX), или go через оболочку. Вы можете сделать последнее либо явным вызовом, используя {"sh", "-c", "ls -l *.c", NULL} в качестве массива, который вы передаете execvp (или аналогично, но без массива, используя execl et c.), Либо вы можете использовать system("ls -l *.c"), который всегда проходит через оболочку.

Обратите внимание, что вы определенно не хотите go проходить через оболочку, если аргументы содержат ненадежный пользовательский ввод, поэтому в этом случае вы расширяете глобусы самостоятельно / используя glob будет путь к go.

0 голосов
/ 03 апреля 2020

Шаблон звездочки * поддерживается оболочкой, но ls.

Вы можете использовать exec с sh, например.

Редактирование Получив ответ от OP, получите все файлы без использования *.c в строковом массиве и отфильтруйте строки, как вы будете sh.

...