You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在execvp调用find时使用"*.c"通配符?目前仅支持完整文件名

我来帮你分析这个问题——其实核心原因是通配符的解析是shell的工作,不是execvp或者find本身,咱们一步步理清楚:

为什么直接用"*.c"不行?

当你在终端敲find -name *.c时,是shell先把*.c展开成当前目录下所有.c结尾的文件名,再把这些文件名传给find——但这其实是错误的用法,因为find的-name选项只接受一个匹配模式,这样会导致find报错(比如提示paths must precede expression)。

正确的shell用法是用引号把*.c括起来:find -name '*.c',这时候shell不会扩展通配符,而是直接把"*.c"作为参数传给find,由find自己解析这个匹配模式,遍历目录找到所有符合条件的文件。

你的代码里直接传"one.c"能正常运行,是因为这是一个具体的文件名,不需要解析;换成"*.c"后,其实相当于shell里的find -name '*.c',理论上应该能找到所有.c文件,如果你觉得不行,大概率是没加错误提示,看不到execvp或find的报错信息。

解决方案1:让find自己处理通配符(推荐,符合find的正确用法)

修改你的代码,把"one.c"换成"*.c",同时加上execvp失败后的错误提示(因为execvp成功的话,后面的代码不会执行,一旦执行就说明出错了):

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

int main(void) {
    printf("running\n");
    char* args[] = { "find", "-name", "*.c", NULL};
    char * envp[] ={NULL};
    int pid = fork();
    switch(pid){
        case -1:
            perror("fork() failed");
            exit(1);
        case 0:
            // child process
            execvp(args[0], args);
            // 能走到这里说明execvp执行失败
            perror("execvp failed");
            exit(1);
        default:
            // parent process
            if(wait(NULL) == -1){
                perror("wait() failed");
            }
    }
    return 0;
}

这样find会自己解析*.c模式,遍历当前目录及子目录找到所有.c结尾的文件。

解决方案2:调用shell来处理通配符(仅当你确实需要shell扩展时用)

如果你非要让*.c先被展开成具体文件名(虽然这不符合find的常规用法),可以通过execvp调用sh -c来让shell完成通配符扩展:

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

int main(void) {
    printf("running\n");
    // 让shell执行完整的find命令,由shell处理通配符
    char* args[] = { "sh", "-c", "find -name *.c", NULL};
    char * envp[] ={NULL};
    int pid = fork();
    switch(pid){
        case -1:
            perror("fork() failed");
            exit(1);
        case 0:
            execvp(args[0], args);
            perror("execvp failed");
            exit(1);
        default:
            if(wait(NULL) == -1){
                perror("wait() failed");
            }
    }
    return 0;
}

注意:这种方式会让shell先把*.c展开成当前目录的.c文件,再传给find,这可能导致find报错(因为-name只能接收一个参数),所以仅在你有特殊需求时使用。

额外补充:手动在程序中扩展通配符

如果你想自己在代码里处理通配符扩展,可以用glob函数实现,不过同样要注意find的语法限制:

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

int main(void) {
    printf("running\n");
    glob_t glob_result;
    // 手动展开*.c通配符
    int ret = glob("*.c", GLOB_ERR, NULL, &glob_result);
    if (ret != 0) {
        perror("glob failed");
        exit(1);
    }

    // 构建参数数组:注意这种用法不符合find的语法,仅作演示
    char** args = malloc((3 + glob_result.gl_pathc) * sizeof(char*));
    args[0] = "find";
    args[1] = "-name";
    for (int i = 0; i < glob_result.gl_pathc; i++) {
        args[2 + i] = glob_result.gl_pathv[i];
    }
    args[2 + glob_result.gl_pathc] = NULL;

    char * envp[] ={NULL};
    int pid = fork();
    switch(pid){
        case -1:
            perror("fork() failed");
            exit(1);
        case 0:
            execvp(args[0], args);
            perror("execvp failed");
            exit(1);
        default:
            if(wait(NULL) == -1){
                perror("wait() failed");
            }
    }

    globfree(&glob_result);
    free(args);
    return 0;
}

内容的提问来源于stack exchange,提问作者code kid

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 09:01:54