Newsgroup: it.comp.lang.c++
Titolo: Find file

Ciao.
Ho bisogno di una funzione che mi torni uno o più file
cercati i tutte le unità dell'hd.....
premetto che conosco il BCB 1.0....
Mi servirà per scrivere un prg. sui midifile----
grazie.
http://pwp.complab.com/maufel

premetto che conosco il BCB 1.0....
Mi pareva di avere gia` dato le indicazioni necessarie,
ma apparentemente cosi` non e`.  Ecco dunque un
programmino giocattolo, che usa solo le nude API e
quindi dovrebbe funzionare con qualsiasi compilatore
di questo mondo; spero che basti ad illustrare come
si trovano i file in Win32 -- facci sapere.  Il programma
e` in C++, ma non usa quasi nessuna feature del C++,
tanto per garantire che funzioni anche con compilatori
matusalemmici; accetta come argomenti le solite
"patttern" alla Windows, tipo pip*.doc per cercare tutti
i file .doc il cui nome inizia con pip, eccetera.  Quando
"fruga" su dischi inesistenti (floppy, cdrom, eccetera)
potrebbe apparire una richiesta di abort/retry/ignore (a
me non succede, su Win98, ma su versioni piu`
vecchie potrebbe anche avvenire); se cio` succede,
si puo` rimediarvi con l'API SetErrorMode.
#define STRICT
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
/*
 * questo programma cerca uno o piu` file in
 * "tutti i dischi"; per ogni file trovato,
 * chiama la funzione "trovato", passandole
 * come parametri il directory e il nome
 * del file.  Qui, ad esempio, la funzione
 * non fa altro che stampare queste info.
 */
typedef void (*trov_t)(const char* directory, const char* filename);
int trova_in_tutti_i_drive(const char* pattern, trov_t funz_trovato);
void trovato(const char* directory, const char* filename)
{
    printf("  Trovato (%s) in %s\n", filename, directory);
}
int
main(int argc, char** argv)
{
    if(argc<2) {
        /* diagnostica di errore se non ho argomenti */
        printf("Uso: %s 1+pattern_da_cercare\n", argv[0]);
        printf("Es: %s pip*.pup\n", argv[0]);
        printf("trova tutti i file pip*.pup in tutti i dischi\n");
        return 100;
    }
    /* ciclo, ripetendo l'operazione su ogni argomento */
    for(int i=1; i<argc; ++i)
        if(trova_in_tutti_i_drive(argv[i], trovato)) break;
    return 0;
}
/* avanza in un "concatenamento" di stringhe
 * terminato da due null consecutivi (quello
 * che ritorna ad esempio la GetLogicalDriveStrings)
 */
static void
next_string(char**p)
{
    while(**p) ++*p;
    ++*p;
}
/* ricerca di un pattern entro un solo directory
 */
int
trova_in_un_directory(const char* directory, const char* pattern,
                      trov_t funz_trovato)
{
    WIN32_FIND_DATA wfd;
    HANDLE hFind = FindFirstFile(pattern, &wfd);
    if(hFind==INVALID_HANDLE_VALUE)
        return 0;
    int totfound=0;
    for(;;) {
        funz_trovato(directory, wfd.cFileName);
        ++totfound;
        if(!FindNextFile(hFind, &wfd))
            break;
    }
    FindClose(hFind);
    return totfound;
}
/* ricerca recursiva di un pattern in un sotto-albero
 */
int
trova_in_un_albero(const char* root, const char* pattern,
                   trov_t funz_trovato)
{
    if(!SetCurrentDirectory(root)) {
        printf("  Non posso esplorare %s, lo salto\n", root);
        return 0;
    }
    int totfound = trova_in_un_directory(root, pattern, funz_trovato);
    WIN32_FIND_DATA wfd;
    HANDLE hFind = FindFirstFile("*.*", &wfd);
    if(hFind==INVALID_HANDLE_VALUE)
        return 0;
    for(;;) {
        /* recursione in subdir, evitando quelli fittizzi . e .. */
        if((wfd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) &&
            strcmp(".",wfd.cFileName) &&
            strcmp("..",wfd.cFileName)) {
                /* prepariamo il path del subdirectory */
                char* subdir = (char*)malloc(strlen(root)+1+
                    strlen(wfd.cFileName)+1);
                strcpy(subdir, root);
                if(root[strlen(root)-1] != '\\')
                    strcat(subdir, "\\");
                strcat(subdir, wfd.cFileName);
                /* la chiamata recursiva */
                totfound += trova_in_un_albero(subdir, pattern, funz_trovato);
                /* cleanup */
                free(subdir);
        }
        if(!FindNextFile(hFind, &wfd))
            break;
    }
    FindClose(hFind);
    return totfound;
}
/*  ricerca iterativa in tutti i drive
 */
int
trova_in_tutti_i_drive(const char* pattern, trov_t funz_trovato)
{
    /* scopriamo quanto spazio ci serve */
    char junk;
    DWORD len = GetLogicalDriveStrings(1, &junk);
    /* lo allochiamo e otteniamo le info */
    char* buf = (char*)malloc(len);
    DWORD rc =  GetLogicalDriveStrings(len, buf);
    if(!rc || (rc > len)) {
        printf("Non posso ottenere le logical drive strings\n");
        free(buf);
        return 1;
    }
    printf("Cerco: %s\n", pattern);
    /* salviamo il current-directory per ripristinarlo alla fine */
    char save_dir[MAX_PATH];
    GetCurrentDirectory(MAX_PATH, save_dir);
    int totfound = 0;
    /* iterazione sui drive */
    for(char* p = buf; *p; next_string(&p)) {
        printf("Nel disco: %s\n", p);
        totfound += trova_in_un_albero(p, pattern, funz_trovato);
    }
    printf("  Trovati %d in tutto\n", totfound);
    free(buf);
    SetCurrentDirectory(save_dir);
    return 0;
}
Alex