[C] Gestione directory.

Linguaggi di programmazione: php, perl, python, C, bash e tutti gli altri.
gila75
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 2739
Iscrizione: mercoledì 16 gennaio 2013, 17:28
Desktop: ubuntu-2d
Distribuzione: Ubuntu 12.04.2 LTS i686
Località: Airuno(Lecco)

Re: [C] Gestione directory.

Messaggio da gila75 »

Rieccomi :)
Ho messo insieme un po' le idee, ripassato un po' la ricorsione e studiato i vari listati proposti, e ho messo in codice ciò che ho capito e a modo mio (nel senso di provare a scrivere
e non fare copia incolla).
Il listato non è completo, con i test sugli errori, e magari in alcuni punti esco senza curarmi se un descrittore è aperto o meno.
comunque per il momento l'importante è capire come copiare directory, sottodirectory e file nell'ordine preciso della cartella d'origine.
Ho apportato una modifica, non so se buona o meno. In termini di velocità credo sia penalizzante, ma risparmio l'allocazione dinamica delle liste o un vettore bidimensionale.
In poche parole al posto di salvare i nomi dei files da copiare in una lista, li leggo e uno ad uno vado nella cartelle destinazione e li copio.
Dopo averli copiati ripristino il percorso (tolgo il nome del file) es:

mia_cartella/file.txt ritorno a mia_cartella/
con un semplice puntatore che inizialmente punta alla fine della stringa, poi rimette il '\0' e il nome del file viene "troncato".
Insomma vi posto il codice...certo non è raffinatissimo, ci devo ancora lavorare :D
Comunque mi avete davvero aiutato, non credevo fosse così un casino copiare cartelle

Codice: Seleziona tutto

#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#include <stdbool.h>  
#define  SIZE_BUF 1024 

    struct dirent *info;
    struct stat info_stat;

int DirWalk(const char *origin, int *cont, int *contDir, char *dest);
void crea_dir(char *copy_dest);
int test_origin(const char *origin);
void copia_files(char *copy_path,char *copy_dest);




void copia_files(char *copy_path,char *copy_dest)
{
    FILE *fpin, *fpout;    
    char static_buf[SIZE_BUF];
    int len,n;
    char *p;

    len=strlen(copy_dest);
    p=&copy_dest[len];
    strncat(copy_dest,info->d_name,PATH_MAX);

    fpin = fopen(copy_path,"rb");     
    if(fpin==NULL)
    {
        puts("errore apertura file");
        exit (1);
    } 

    fpout = fopen(copy_dest, "wb"); 
    if(fpin==NULL)
    {
        puts("errore apertura file");
        exit (1);
    } 
    
    for(;;) 
    {              
        n = fread(static_buf, 1, SIZE_BUF, fpin);    
        if( n == 0 ) 
        {
            break;
        }       
        
        fwrite(static_buf, 1, n, fpout);   
    }
    fclose(fpin);     
    fclose(fpout);
    // ripristino percorso: cartella/sotto_cart/file.txt-->>cartella/sotto_cart/
    *p='\0';
}



int test_origin(const char *origin)
{
    DIR *dir;
 
    if ((dir = opendir(origin)) == NULL)
    {
        printf ("Impossibile aprire la directory %s\n", origin);
        return 0;
    }
    
    else
    {
        closedir(dir); 
        return 1;
    }
}


void crea_dir(char *copy_dest)
{
    int res;
    int len;
    
    res= mkdir(copy_dest, S_IRWXU);
    if (res!=0) 
    {
        printf ("errore nella creazione della cartella %s\n", copy_dest);
        exit (EXIT_FAILURE);
        
    }

    len=strlen(copy_dest);
    copy_dest[len]='/';
    len++;
    copy_dest[len]='\0';
    
}

int DirWalk(const char *origin, int *cont, int *contDir, char *dest)
{
    DIR *dir;
    char temp[PATH_MAX+1];
    char path[PATH_MAX + 1];
   
    strncpy(temp,dest,PATH_MAX);
    

    /* Apro il descrittore della directory */
    if ((dir = opendir(origin)) == NULL)
    {
        printf ("Impossibile aprire la directory %s\n", origin);
        exit (EXIT_FAILURE);
    }
           
    /* Finché ci sono file all'interno della directory... */
    while ((info = readdir(dir)) != NULL)
    {
        if ((strncmp(info->d_name, ".", PATH_MAX) == 0) || (strncmp(info->d_name, "..", PATH_MAX) == 0 ))
        {
            continue;
        }
      
      strncpy(path, origin, PATH_MAX);
      strncat(path, "/", PATH_MAX);
      strncat(path, info->d_name, PATH_MAX);
      stat(path, &info_stat);

        if(S_ISREG(info_stat.st_mode) == true)
        {
            (*cont)++;
            copia_files(path,dest);
         
        }
        else if(S_ISDIR(info_stat.st_mode) == true)
        {
            (*contDir)++;
            strncat (dest,info->d_name,PATH_MAX);         
            crea_dir(dest);   
            DirWalk(path, cont, contDir,dest);
            
        }
            strncpy(dest,temp,PATH_MAX);
            
    }
           
    closedir(dir);
    return 0;    
}

int main(void)
{
    char origin[PATH_MAX + 1];
    char dest  [PATH_MAX + 1];
    int len;
    int cont = 0;
    int contDir = 0;
    
    
    printf ("immetti cartella origine: ");
    fgets (origin, PATH_MAX, stdin);
    len = strnlen(origin, PATH_MAX);
    len--;
    origin[len] = '\0';
    
    printf ("immetti cartella dest: ");
    fgets (dest, PATH_MAX, stdin);
    len = strnlen(dest, PATH_MAX);
    len--;
    dest[len] = '\0';
    

    if ( (test_origin(origin))==1)
        crea_dir(dest);
    else
    {
        printf ("la cartella [%s] non esiste\n",origin);
        return 0;
    }    
    
    DirWalk(origin, &cont, &contDir,dest);
       
    printf ("numero regular files : %d\n", cont);    
    printf ("numero directory     : %d\n", contDir);        
       
    return 0;
}
Siccome non mi piace prendere meriti non mie, parti del codice sono state proposte da @Vincenzo1968, che ringrazio davvero
Dategli un occhio se avete voglia. A me sembra (sembra) esente da bugs e copia correttamente
gila75
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 2739
Iscrizione: mercoledì 16 gennaio 2013, 17:28
Desktop: ubuntu-2d
Distribuzione: Ubuntu 12.04.2 LTS i686
Località: Airuno(Lecco)

Re: [C] Gestione directory.

Messaggio da gila75 »

Ho ampliato il programma per la copia di una directory.
prima si poteva fare solo copia da :
sorgente--->destinazione esempio : mia_cartella--->nuova_cartella.
Ma non era possibile fare mia_cartella---->nuova_cartella/sotto_cartella e copiare tutto in sotto_cartella.
Ora invece è possibile.
Ho messo anche dei controlli sulla stringa d'input per la destinazione. Se per esempio (erroneamente) dovessimo inserire
mia_cartella---->nuova_cartella/a/b//c
verrebbero create delle cartelle vuote (nuova_cartella+a+b) ma la creazione di c fallirebbe per via dei doppi // quindi la ci rimarrebbero cartelle vuote per nulla.
Il tutto è implementato con un do/wile e la funzione "test_percorso".
Ecco il programma completo

Codice: Seleziona tutto

#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#include <stdbool.h>  
#define  SIZE_BUF 2048 

    struct dirent *info;
    struct stat info_stat;

int apertura_ricorsiva(const char *origin, int *cont, int *contDir, char *dest);
void crea_dir(char *copy_dest);
int test_origin(const char *origin);
void copia_files(char *copy_path,char *copy_dest);
void analizza_path (char *copy_dest, int lenght);
void crea_sotto_dir (char *copy_temp);
int test_percorso (char *copy_dest, int len_dest);



int test_percorso (char *copy_dest, int len_dest)
{
    int i;
    
    for (i=0; i<=len_dest; i++)
        {
            if (copy_dest[i]=='/' && copy_dest[i+1]=='/')
                return 0;
        }
   
    return 1;
}





void crea_sotto_dir (char *copy_temp)

{
        
    if ((mkdir(copy_temp, S_IRWXU)!=0))
    
    {
        printf("Errore creazione %s\n",copy_temp);
        exit(1);
    }
    
}




void analizza_path (char *copy_dest, int lenght)
{
    int i;
    char temp_dest[PATH_MAX+1];

    for (i=0; i<=lenght ; i++)
    {
        if (copy_dest[i]!='/' )
        {
            temp_dest[i]=copy_dest[i];
        }
        
        if (copy_dest[i]=='/' )
        {
            temp_dest[i]='/';
            temp_dest[i+1]='\0';
            crea_sotto_dir(temp_dest);
        }
        
        if (copy_dest[i]=='\0')
            crea_sotto_dir(temp_dest);
    }
            
    strncpy (copy_dest,temp_dest,PATH_MAX);
    lenght=strlen(copy_dest);
    copy_dest[lenght]='/';
    copy_dest[lenght+1]='\0';
        
}

    




void copia_files(char *copy_path,char *copy_dest)
{
    FILE *fpin, *fpout;    
    char static_buf[SIZE_BUF];
    int len,n;
    char *p;

    len=strlen(copy_dest);
    p=&copy_dest[len];
    strncat(copy_dest,info->d_name,PATH_MAX);

    fpin = fopen(copy_path,"rb");     
    if(fpin==NULL)
    {
        puts("errore apertura file");
        exit (1);
    } 

    fpout = fopen(copy_dest, "wb"); 
    if(fpin==NULL)
    {
        puts("errore apertura file");
        exit (1);
    } 
    
    for(;;) 
    {              
        n = fread(static_buf, 1, SIZE_BUF, fpin);    
        if( n == 0 ) 
        {
            break;
        }       
        
        fwrite(static_buf, 1, n, fpout);   
    }
    fclose(fpin);     
    fclose(fpout);
    // ripristino percorso: cartella/sotto_cart/file.txt-->>cartella/sotto_cart/
    *p='\0';
}



int test_origin(const char *origin)
{
    DIR *dir;
 
    if ((dir = opendir(origin)) == NULL)
    {
        printf ("Impossibile aprire la directory %s\n", origin);
        return 0;
    }
    
    else
    {
        closedir(dir); 
        return 1;
    }
}


void crea_dir(char *copy_dest)
{
    int res;
    int len;
    
    res= mkdir(copy_dest, S_IRWXU);
    if (res!=0) 
    {
        printf ("errore nella creazione della cartella %s\n", copy_dest);
        exit (EXIT_FAILURE);
        
    }

    len=strlen(copy_dest);
    copy_dest[len]='/';
    len++;
    copy_dest[len]='\0';
    
}

int apertura_ricorsiva(const char *origin, int *cont, int *contDir, char *dest)
{
    DIR *dir;
    char temp[PATH_MAX+1];
    char path[PATH_MAX + 1];
   
    strncpy(temp,dest,PATH_MAX);
    

    /* Apro il descrittore della directory */
    if ((dir = opendir(origin)) == NULL)
    {
        printf ("Impossibile aprire la directory %s\n", origin);
        exit (EXIT_FAILURE);
    }
           
    /* Finché ci sono file all'interno della directory... */
    while ((info = readdir(dir)) != NULL)
    {
        if ((strncmp(info->d_name, ".", PATH_MAX) == 0) || (strncmp(info->d_name, "..", PATH_MAX) == 0 ))
        {
            continue;
        }
      
      strncpy(path, origin, PATH_MAX);
      strncat(path, "/", PATH_MAX);
      strncat(path, info->d_name, PATH_MAX);
      stat(path, &info_stat);

        if(S_ISREG(info_stat.st_mode) == true)
        {
            (*cont)++;
            copia_files(path,dest);
         
        }
        else if(S_ISDIR(info_stat.st_mode) == true)
        {
            (*contDir)++;
            strncat (dest,info->d_name,PATH_MAX);         
            crea_dir(dest);   
            apertura_ricorsiva(path, cont, contDir,dest);
            
        }
            strncpy(dest,temp,PATH_MAX);
            
    }
           
    closedir(dir);
    return 0;    
}

int main(void)
{
    char origin[PATH_MAX + 1];
    char dest  [PATH_MAX + 1];
    int len;
    int cont = 0;
    int contDir = 0;
    
    
    printf ("immetti cartella origine: ");
    fgets (origin, PATH_MAX, stdin);
    len = strnlen(origin, PATH_MAX);
    len--;
    origin[len] = '\0';
    
    do  
    {
        printf ("immetti cartella dest: ");
        fgets (dest, PATH_MAX, stdin);
        len = strnlen(dest, PATH_MAX);
        len--;
        dest[len] = '\0';
    }   while (dest[len-1]=='/' || ((test_percorso(dest,len)==0)) );

    

    if ( (test_origin(origin))==0)
    {
        printf ("la cartella [%s] non esiste\n",origin);
        return 0;
    }    
    
    analizza_path (dest,len);
    apertura_ricorsiva(origin, &cont, &contDir,dest);
    
       
    printf ("numero regular files : %d\n", cont);    
    printf ("numero directory     : %d\n", contDir);        
       
    return 0;
}
Se vi va date un occhio, credo sia tutto a posto.
Purtroppo non posso ancora fare
a/sotto_cartella---->b/sotto_cartella... ma proverò anche a fare quello
gila75
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 2739
Iscrizione: mercoledì 16 gennaio 2013, 17:28
Desktop: ubuntu-2d
Distribuzione: Ubuntu 12.04.2 LTS i686
Località: Airuno(Lecco)

Re: [C] Gestione directory.

Messaggio da gila75 »

Posto la versione definitiva (bugs permettendo)

Ho aggiunto un po' di opzioni le elenco qui

Codice: Seleziona tutto

OPERAZIONI PERMESSE:
dir_origine---->dir_dest
dir_origine/sotto_dir_origine---->dir_dest  
dir_origine/sotto_dir_origine---->dir_dest/sotto_dir_dest (sotto_dir_dest può non esistere e viene creata)

OPERAZIONI NEGATE:
dir_origine----->dir_origine  (stesso percorso)
dir_dest/sotto_dir//mia_cartella (i doppi slash sono negati)
dir_dest/ (slash finale negato)
e questo il codice completo. Se qualcuno dovesse rilevare bugs mi faccia sapere:

Codice: Seleziona tutto

#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#include <stdbool.h>  
#define  SIZE_BUF 2048 

    struct dirent *info;
    struct stat info_stat;

int apertura_ricorsiva(const char *origin, int *cont, int *contDir, char *dest);
void crea_dir(char *copy_dest);
int test_origin(const char *origin);
void copia_files(char *copy_path,char *copy_dest);
void analizza_path (char *copy_dest, int lenght);
void crea_sotto_dir (char *copy_temp);
int test_percorso (char *copy_dest, int len_dest);
void test_percorso_uguale (char *origin, char *dest);


void test_percorso_uguale (char *origin, char *dest)
{
    int len_origin;
    
    len_origin=strlen(origin);
    if ((strncmp(origin,dest,len_origin)==0))
    {
        printf ("Errore:i percorsi coincidono\n");
        exit (EXIT_FAILURE);
    }
}    


int test_percorso (char *copy_dest, int len_dest)
{
    int i;
    
    for (i=0; i<=len_dest; i++)
        {
            if (copy_dest[i]=='/' && copy_dest[i+1]=='/')
                return 0;
        }
   
    return 1;
}





void crea_sotto_dir (char *copy_temp)

{
    DIR *dir_2;
    int flag=0;
    int flag_1=0;    

    if ((mkdir(copy_temp, S_IRWXU)!=0))  
    {
        flag=1;
    }
    
    if ((dir_2 = opendir(copy_temp)) == NULL)
    {
        flag_1=1;
    }
    if (flag_1==1 && flag==1)
    {
        printf ("Errore generico\n");
        if (dir_2!=NULL)
            closedir(dir_2);
        exit (EXIT_FAILURE);
    }

    

    if ((dir_2)!=NULL)
        closedir(dir_2);

}




void analizza_path (char *copy_dest, int lenght)
{
    int i;
    char temp_dest[PATH_MAX+1];

    for (i=0; i<=lenght ; i++)
    {
        if (copy_dest[i]!='/' )
        {
            temp_dest[i]=copy_dest[i];
        }
        
        if (copy_dest[i]=='/' )
        {
            temp_dest[i]='/';
            temp_dest[i+1]='\0';
            crea_sotto_dir(temp_dest);
        }
        
        if (copy_dest[i]=='\0')
            crea_sotto_dir(temp_dest);
    }
            
    strncpy (copy_dest,temp_dest,PATH_MAX);
    lenght=strlen(copy_dest);
    copy_dest[lenght]='/';
    copy_dest[lenght+1]='\0';
        
}

    




void copia_files(char *copy_path,char *copy_dest)
{
    FILE *fpin, *fpout;    
    char static_buf[SIZE_BUF];
    int len,n;
    char *p;

    len=strlen(copy_dest);
    p=&copy_dest[len];
    strncat(copy_dest,info->d_name,PATH_MAX);

    fpin = fopen(copy_path,"rb");     
    if(fpin==NULL)
    {
        puts("errore apertura file");
        if (fpin!=NULL)
            fclose(fpin);
        exit (EXIT_FAILURE);
    } 

    fpout = fopen(copy_dest, "wb"); 
    if(fpin==NULL)
    {
        puts("errore apertura file");
        if (fpout!=NULL)
            fclose(fpout);
        exit (EXIT_FAILURE);
    } 
    
    for(;;) 
    {              
        n = fread(static_buf, 1, SIZE_BUF, fpin);    
        if( n == 0 ) 
        {
            break;
        }       
        
        fwrite(static_buf, 1, n, fpout);   
    }
    fclose(fpin);     
    fclose(fpout);
    // ripristino percorso: cartella/sotto_cart/file.txt-->>cartella/sotto_cart/
    *p='\0';
}



int test_origin(const char *origin)
{
    DIR *dir;
 
    if ((dir = opendir(origin)) == NULL)
    {
        printf ("Impossibile aprire la directory %s\n", origin);
        return 0;
    }
    
    else
    {
        closedir(dir); 
        return 1;
    }
}


void crea_dir(char *copy_dest)
{
    
    int len;
    
    if  ((mkdir(copy_dest, S_IRWXU))!=0)
    
    {
        printf ("errore nella creazione della cartella %s\n", copy_dest);
        exit (EXIT_FAILURE);
        
    }

    len=strlen(copy_dest);
    copy_dest[len]='/';
    len++;
    copy_dest[len]='\0';
    
}

int apertura_ricorsiva(const char *origin, int *cont, int *contDir, char *dest)
{
    DIR *dir;
    char temp[PATH_MAX+1];
    char path[PATH_MAX + 1];
   
    strncpy(temp,dest,PATH_MAX);
    

    /* Apro il descrittore della directory */
    if ((dir = opendir(origin)) == NULL)
    {
        printf ("Impossibile aprire la directory %s\n", origin);
            if (dir!=NULL)
            closedir(dir);
        exit (EXIT_FAILURE);
    }
           
    /* Finché ci sono file all'interno della directory... */
    while ((info = readdir(dir)) != NULL)
    {
        if ((strncmp(info->d_name, ".", PATH_MAX) == 0) || (strncmp(info->d_name, "..", PATH_MAX) == 0 ))
        {
            continue;
        }
      
      strncpy(path, origin, PATH_MAX);
      strncat(path, "/", PATH_MAX);
      strncat(path, info->d_name, PATH_MAX);
      stat(path, &info_stat);

        if(S_ISREG(info_stat.st_mode) == true)
        {
            (*cont)++;
            copia_files(path,dest);
         
        }
        else if(S_ISDIR(info_stat.st_mode) == true)
        {
            (*contDir)++;
            strncat (dest,info->d_name,PATH_MAX);         
            crea_dir(dest);   
            apertura_ricorsiva(path, cont, contDir,dest);
            
        }
            strncpy(dest,temp,PATH_MAX);
            
    }
           
    closedir(dir);
    return 0;    
}

int main(void)
{
    char origin[PATH_MAX + 1];
    char dest  [PATH_MAX + 1];
    int len;
    int cont = 0;
    int contDir = 0;
    
    
    printf ("immetti cartella origine: ");
    fgets (origin, PATH_MAX, stdin);
    len = strnlen(origin, PATH_MAX);
    len--;
    origin[len] = '\0';
    
    do  
    {
        printf ("immetti cartella dest: ");
        fgets (dest, PATH_MAX, stdin);
        len = strnlen(dest, PATH_MAX);
        len--;
        dest[len] = '\0';
    }   while (dest[len-1]=='/' || ((test_percorso(dest,len)==0)) );

    

    if ( (test_origin(origin))==0)
    {
        printf ("la cartella [%s] non esiste\n",origin);
        return 0;
    }    
    
    test_percorso_uguale(origin,dest);
    analizza_path (dest,len);
    apertura_ricorsiva(origin, &cont, &contDir,dest);
    
       
    printf ("numero regular files : %d\n", cont);    
    printf ("numero directory     : %d\n", contDir);        
       
    return 0;
}
Forse alcuni controlli della funzione void crea_sotto_dir non sono necessari... dovrei appurare.
Scrivi risposta

Ritorna a “Programmazione”

Chi c’è in linea

Visualizzano questa sezione: 0 utenti iscritti e 4 ospiti