Last update June 10, 2005

Helmut Leitner /
Dir Find File



This a snippet that scans the a directory (and if you want all subdirectories) for files and/or directories. You provide the starting directory, a wildcard specification to filter the entities found. You may execute arbitrary code using DirFindFileCall (that's where D closures come in) or just fetch the names in an array using DirFindFile.

The module pavel.windows refers to "windows.d" from Pavel Minayev. You may have to adapt this import statement to fit your include-directory-layout.

/*
** dirlist.d (C) Helmut Leitner 2003
** first D program, don't rely on it
** will become a module under FDL when ready
*/

import string;
import c.stdio;
import pavel.windows;

const int DFF_FILES = 1;
const int DFF_DIRS = 2;
const int DFF_RECURSE = 4;

alias WIN32_FIND_DATA FILEINFO;
alias char [] String;

int FileInfoRetDirFlag(FILEINFO *fb)
{
    int flag = 0;

    if(fb.cFileName[0] != '.' && 
       (fb.dwFileAttributes & (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)) == 0) {
        if(fb.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
            flag = 1;
        }
    }
    return flag;
}

int FileInfoRetFileFlag(FILEINFO *fb)
{
    int flag = 0;

    if(fb.cFileName[0] != '.' && 
        (fb.dwFileAttributes & (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)) == 0) {
        if((fb.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) == 0) {
            flag = 1;
        }
    }
    return flag;
}

int FileExtCmp(char *s1,char *s2)
{
    while(*s1 && *s2) {
        if(*s1 == '*' || *s2 == '*') {
            return 0;
        }
        if(*s1 != *s2 && *s1 != '?' && *s2 != '?') {
            return -1;
        }
        s1++; s2++;
    }
    if(*s1 == '*' || *s2 == '*') {
        return 0;
    }
    if(*s1 == *s2) {
        return 0;
    }
    return -1;
}

int FileNameCmp(String fnam1,String fnam2)
{
    String [] a1 = split(toupper(fnam1),'.');
    String [] a2 = split(toupper(fnam2),'.');

    if(a1.length < 2) {
        a1 ~= '';
    }
    if(a2.length < 2) {
        a2 ~= '';
    }

    if(FileExtCmp(a1[0],a2[0])) {
        return -1;
    }
    if(FileExtCmp(a1[1],a2[1])) {
        return -1;
    }

    return 0;
}

int DirFindFileCall(String dir, String fspec,int delegate (String d,String fn,WIN32_FIND_DATA *b) f, int flags)
{
    WIN32_FIND_DATA b;
    BOOL done = false;
    int err = 0;
    String fnam2;
    String dir2;

    HANDLE hd=FindFirstFileA(dir ~ "*.*", &b);
    while((hd != INVALID_HANDLE_VALUE) && (done == false))
    {
        fnam2 = toString(b.cFileName); // !!! has me bitten
        //printf("%.*s\n",fnam2);
        if(FileInfoRetFileFlag(&b)) {
            if(flags & DFF_FILES) {
                if(FileNameCmp(fnam2,fspec) == 0) {
                    if(f(dir,fnam2,&b)) {
                        goto do_exit;
                    }
                }
            }
        }
        if(FileInfoRetDirFlag(&b)) {
            if(flags & DFF_DIRS) {
                if(f(dir,fnam2,&b)) {
                    err = -1;
                    goto do_exit;
                }
            }
            if(flags & DFF_RECURSE) {
                dir2 = dir ~ fnam2 ~ '\';
                if(DirFindFileCall(dir2,fspec,f,flags)) {
                    goto do_exit;
                }
            }
        }
        done = (FindNextFileA(hd,&b) == FALSE);
    }
do_exit:
    if(hd) {
        FindClose(hd);
    }
    return err;
}

String [] DirFindFile(String dir,String fspec, int flags)
{
    String [] files;

    DirFindFileCall(dir,fspec,
        delegate int (String dir, String fnam, WIN32_FIND_DATA *b)
        {
            files ~= (dir ~ fnam);
            return 0;
        }
        ,flags
    );
    return files;
}

int main (String [] args)
{
    String [] paths;

    printf("Files via DirFindFileCall:\n");
    DirFindFileCall('c:\d\','*.d',
        delegate int (String dir, String fnam, WIN32_FIND_DATA *b)
        {
            printf("%.*s%.*s\n",dir,fnam); return 0;
        }
        ,DFF_FILES|DFF_RECURSE
    );
    printf("\n");

    printf("Files via DirFindFile:\n");
    paths = DirFindFile('c:\d\','*.d',DFF_FILES|DFF_RECURSE);
    for(int i = 0; i<paths.length; i++) {
        printf("File[%d]: %.*s\n",i,paths[i]);
    }
    printf("\n");

    printf("Directories via DirFindFile:\n");
    paths = DirFindFile('c:\d\','*.*',DFF_DIRS|DFF_RECURSE);
    for(int i = 0; i<paths.length; i++) {
        printf("Dir[%d]: %.*s\n",i,paths[i]);
    }
    return 0;
}


FolderExamples
FrontPage | News | TestPage | MessageBoard | Search | Contributors | Folders | Index | Help | Preferences | Edit

Edit text of this page (date of last change: June 10, 2005 3:54 (diff))