C:提供正则表达式作为open()的参数?

时间:2015-03-30 22:12:24

标签: c regex linux

有没有办法在不知道其全名的情况下使用open()打开文件? 通过接受正则表达式作为输入,linux shell提供了一种简单的方法(在某种意义上) 例如,如果您有一个包含文件的文件夹:

a.out  file1  file2  file3  file4  file.txt  test

并且您希望仅列出前缀为file的文件,您可以通过以下方式执行此操作:

$ ls file*
file1  file2  file3  file4  file.txt

或者:

$ ls file[1-9]
file1  file2  file3  file4

仅列出编号的文件,依此类推......

每当我的程序启动时,我都需要打开相同的文件 问题是,它需要打开的文件格式为:X*Y,意味着它以X开头,以Y结尾,但它可能介于两者之间。
例如,它可以是X-Toshiba_12.45y9-Y,也可以是X-Dell-5.44s-Y 我希望能够在不考虑模型的情况下打开此文件 该文件可能与该文件夹中的其他文件一起存在,但X前缀和Y后缀是唯一的。
我可以迭代该文件夹中的文件并尝试通过匹配字符串找到我的文件,但我宁愿避免它。
有没有办法以某种方式为open()提供正则表达式?

2 个答案:

答案 0 :(得分:4)

这些不是regular expressions!你在谈论glob patterns

您可以使用POSIX.1-2001 glob()函数将glob模式(如*.*foo-*.?a**.[a-z]*等)扩展为数组与给定模式匹配的文件名/路径名(从当前工作目录开始,除非模式指定绝对路径)。这基本上是大多数shell在扩展文件名模式时使用的。

如果你非常喜欢使用正则表达式指定文件名(比如说,你需要find - 类型行为,但使用正则表达式),请使用SUSv4 nftw()函数遍历目录树 - 它甚至可以处理边角情况,例如描述符少于树深度,或者在树遍历时修改,重命名或移动文件,以及POSIX regex函数来过滤文件名。注意:regcomp()regexec()等内置于POSIX.1-2001支持C库,其中包括Linux的所有当前C库实现。根本不需要外部库。

这让我很伤心使用opendir() / readdir()遍历一个目录树,当nftw()是可用的和更聪明和更健壮的示例代码看到。只需定义_XOPEN_SOURCE 700_POSIX_C_SOURCE 200809L以获得Linux和许多* BSD变体中的所有这些优秀功能。

答案 1 :(得分:1)

检查此示例

#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <dirent.h>

int
startswith(const char *const haystack, const char *const needle)
 {
    size_t haystackLength;
    size_t needleLength;   

    if ((haystack == NULL) || (needle == NULL))
        return 0;

    haystackLength = strlen(haystack);
    needleLength   = strlen(needle);

    if (haystackLength < needleLength)
        return 0;

    return (memcmp(haystack, needle, needleLength) == 0);
 }

int
endswith(const char *const haystack, const char *const needle)
 {
    size_t haystackLength;
    size_t needleLength;

    if ((haystack == NULL) || (needle == NULL))
        return 0;

    haystackLength = strlen(haystack);
    needleLength   = strlen(needle);

    if (haystackLength < needleLength)
        return 0;

    return (memcmp(haystack + haystackLength - needleLength, needle, needleLength) == 0);
 }

void
searchdir(const char *const directory, const char *const starts, const char *const ends)
 {
    DIR           *dir;
    struct dirent *entry;

    dir = opendir(directory);
    if (dir == NULL)
        return;
    while ((entry = readdir(dir)) != NULL)
     {
        struct stat statbuf;
        char        filepath[PATH_MAX];
        size_t      length;
        const char *name;

        name = entry->d_name;
        if ((strcmp(name, ".") == 0) || (strcmp(name, "..") == 0))
            continue;      

        length = snprintf(filepath, sizeof(filepath), "%s/%s", directory, name);
        if (length >= sizeof(filepath))
         {
            fprintf(stderr, "unexpected error\n");
            closedir(dir);

            return;
         }

        if (stat(filepath, &statbuf) == -1)
         {
             fprintf(stderr, "cannot stat `%s'\n", filepath);
             continue;
         }

        /* if the entry is a directory, probably recures */
        if (S_ISDIR(statbuf.st_mode) != 0)
            saerchdir(filepath, starts, ends);
        /* or just, continue? */

        /* The file name does not match */
        if ((startswith(name, starts) == 0) || (endswith(name, ends) == 0))
            continue;
        /* Do whatever you want with the file */     
        fprintf(stdout, "%s\n", filepath);
     }
    closedir(dir);    
 }

int
main(int argc, char **argv)
{
    if (argc < 4)
     {
        fprintf(stderr, "usage: %s directory startpattern endpattern\n", argv[0]);
        fprintf(stderr, "\tex. %s /home/${USER} X Y\n", argv[0]);

        return -1;
     }
    searchdir(argv[1], argv[2], argv[3]);

    return 0;
}

对文件执行任何操作,可以将其推送到char *数组,将函数指针传递给函数并在文件路径上执行该函数。