Listing directories and sub directories

imrantechi's Avatar author of Listing directories and sub directories
This is an article on Listing directories and sub directories in Win32.

Introduction



This code helps us to list all the files and folders within a directory and sub-directory.

Background



The code should be written in win32 projects as a console application.

Code: C
#include <windows.h>
#include <string.h>
#include <stdio.h>
#include <conio.h>

//macro
#define DEFAULTSIZE 10

#define INTERNALTRAVERSING 1

#define FIRSTLEVELTRAVERSING 0

int main(int argc, char *argv[])
{
    char* DirSpec; 
   
    int traversal;
   
    char* substring;
   
    //  argv[1]="c:";
   
    //  argv[2]="/s";
   
    //  argc=2;
   
    printf ("Target directory is %s.\n", argv[1]);
   
    DirSpec=(char*)calloc ( strlen(argv[1])+1,sizeof(char))
       
        strcpy(DirSpec,argv[1]);       
   
    printf("Name \t\t\t\t Dir/Size \t Created \t     Attributes");
   
    if(strcmp(argv[2],"/s")==0){
       
        traversal=INTERNALTRAVERSING;   
       
    }else{
       
        traversal=FIRSTLEVELTRAVERSING; 
       
    }
   
    if(FindMatch(DirSpec)!=1){
       
        if(GetFileAttributes(DirSpec)==FILE_ATTRIBUTE_DIRECTORY){
           
            substring=NULL;
           
            strcat(DirSpec,"\\*");
           
        }else{
           
            substring=GetSubstring(DirSpec);
        }
       
    }else{
       
        substring=NULL;
    }
   
    WalkFolder(DirSpec,traversal,substring);      
   
    _getch();
   
    free(DirSpec);             
   
    return (0);
   
}


void Display(WIN32_FIND_DATA *pFindFileData)
{   
   
    LPSYSTEMTIME lpst;   
   
    lpst=(LPSYSTEMTIME)calloc(1,sizeof(SYSTEMTIME));    //allocates memory for lpst.
   
    FileTimeToSystemTime(&pFindFileData->ftCreationTime,lpst); //converts the time to system time.
   
    if(pFindFileData->nFileSizeLow==0)
       
        printf ("\n %s \t\t\t\t <Dir>\t\t ", pFindFileData->cFileName);
   
    else
       
        printf("\n %s \t %d \t ",pFindFileData->cFileName,pFindFileData->nFileSizeLow);
   
    printf("%d/%d/%d %d:%d:%d \t ",lpst->wDay,lpst->wMonth,lpst->wYear,lpst->wHour,lpst->wMinute,lpst->wSecond);                       
    PrintFileAttribute(pFindFileData->dwFileAttributes);
   
    free(lpst);   //frees the memory allocated for lpst.
   
}

void WalkFolder (char* pPath,BOOL pSub_folders,char* pSubstr)
{
    WIN32_FIND_DATA FindFileData;
    HANDLE hFind;
    DWORD dwError;
    char ** allpath;
   
    int index=0,i;
   
    static int no_of_files=0;
   
    static int no_of_folders=0;
   
    printf("\n .................................................................");
   
    printf("\n The display is for the path %s \n ", pPath);
   
    allpath=(char **)calloc(DEFAULTSIZE,sizeof(char*));
   
    hFind= INVALID_HANDLE_VALUE;
   
    hFind = FindFirstFile(pPath, &FindFileData);
   
    if (hFind == INVALID_HANDLE_VALUE && pSub_folders!=INTERNALTRAVERSING ) {
       
        printf ("Invalid file handle. Error is %u\n", GetLastError());
       
       
    } else if(hFind!= INVALID_HANDLE_VALUE && pSubstr !=NULL){
       
        PrintFileInfo(hFind,&FindFileData,&no_of_files);
       
    }
   
    if(pSubstr !=NULL && pSub_folders==INTERNALTRAVERSING){
       
        RemoveSubString(pPath,pSubstr);
       
        hFind = FindFirstFile(pPath, &FindFileData);
       
    }
   
    do{
       
        if(pSubstr==NULL){
           
            Display(&FindFileData);
           
        }
       
        if(FindFileData.nFileSizeLow==0 && (strcmp(FindFileData.cFileName,".")!=0)
            && (strcmp(FindFileData.cFileName,"..")!=0)&& pSub_folders==INTERNALTRAVERSING){
           
            if((index+1)%DEFAULTSIZE==0 && index>0){
               
                allpath=(char **)realloc(allpath,(index+DEFAULTSIZE));
               
            }
            allpath[index]=GetNewPath(pPath,FindFileData.cFileName,pSubstr);
            index++;
           
        }else if(FindFileData.nFileSizeLow!=0 && pSubstr==NULL){
           
            no_of_files++;
           
        }if(FindFileData.nFileSizeLow==0 ){
           
            no_of_folders++;
        }
       
       }while (FindNextFile(hFind, &FindFileData) != 0 );
   
   
    for(i=0;i<index;i++){
       
        WalkFolder(allpath[i],pSub_folders,pSubstr);
    }
   
    dwError = GetLastError();
   
    FindClose(hFind);
    if (dwError != ERROR_NO_MORE_FILES)
    {
        printf ("FindNextFile error. Error is %u\n", dwError);
       
    }
   
   
}

char * GetNewPath(char* pPath,char *pFileName,char* pType)
{
   
    char* path;
   
    if(pType==NULL){
       
        path=(char*)calloc(strlen(pPath)+strlen(pFileName)+1,sizeof(char));
       
    }else{
       
        path=(char*)calloc(strlen(pPath)+strlen(pFileName)+strlen(pType)+1,sizeof(char));
       
    }
   
    strcpy(path,pPath);
    path[strlen(path)-1]='\0';
    strcat(path,pFileName);
    if(pType==NULL){
        strcat(path,"\\*");
    }else{
        strcat(path,pType);
    }
    return path;
   
}


int FindMatch(char* pPath)
{
    int i;
   
    i=strlen(pPath)-1;
   
    if(pPath[i]=='*'&& pPath[i-1]=='\\'){
       
        return 1;
    }
    return 0;
}

char* GetSubstring(char* pPath)
{
   
    char* substring;
    int i;
    int length;
   
    for(i=strlen(pPath)-1;i>0;i--){
       
        if(pPath[i]=='\\')
            break;
    }
   
    length=strlen(pPath)+1-i;
    substring=(char*)calloc(length,sizeof(char));
    strcpy(substring,(pPath+i));
    return substring;
}

void RemoveSubString(char *pPath,char* pSubstr)
{
    int len;
   
    len=strlen(pPath)-strlen(pSubstr)+4;
    pPath=(char*)realloc(pPath,(len));
    //len=strlen(pPath);
    pPath[len-4]='\0';
    strcat(pPath,"\\*.");
}

void PrintFileInfo(HANDLE hFind,WIN32_FIND_DATA *FindFileData,int *no_of_files)
{
   
    do{
       
        Display(FindFileData);
       
        *no_of_files++;
       
    }while(FindNextFile(hFind, FindFileData) != 0 );
   
}

void PrintFileAttribute(DWORD   fileAttribute)
{
    int  index;               ///< holds the index of attribute array
    int  flag;                    ///< holds the flag value
   
    ///< attribute array holds the file all attributes
    int  attribute[12] = {FILE_ATTRIBUTE_READONLY,
        FILE_ATTRIBUTE_HIDDEN,
        FILE_ATTRIBUTE_SYSTEM,
        FILE_ATTRIBUTE_DIRECTORY,
        FILE_ATTRIBUTE_ARCHIVE,
        FILE_ATTRIBUTE_DEVICE,
        FILE_ATTRIBUTE_NORMAL,
        FILE_ATTRIBUTE_TEMPORARY,
        FILE_ATTRIBUTE_SPARSE_FILE,
        FILE_ATTRIBUTE_REPARSE_POINT,
        FILE_ATTRIBUTE_COMPRESSED,
        FILE_ATTRIBUTE_OFFLINE};
   
    //Assign starting value zero to count
    index =0;
    //printf("\t");
   
    //loop continue upto fileattribute greaterthan attribute[count]
    while (fileAttribute >=(unsigned long) attribute[index]) {
       
        //flag holds attribute value
        flag = fileAttribute & attribute[index++];
       
        switch (flag) {
           
            //if the file attribute is readonly
        case FILE_ATTRIBUTE_READONLY:
            printf( "R ");
            break;
            //if the file attribute is hidden
        case FILE_ATTRIBUTE_HIDDEN:
            printf( "H ");
            break;
           
            //if the file attribute is system
        case FILE_ATTRIBUTE_SYSTEM:
            printf( "S ");
            break;
           
            //if the file attribute is archive
        case FILE_ATTRIBUTE_ARCHIVE:
            printf( "A ");
            break;
           
            //if the file attribute is device
        case FILE_ATTRIBUTE_DEVICE:
            printf( "D ");
            break;
           
            //if the file attribute is normal
        case FILE_ATTRIBUTE_NORMAL:
            printf( "N ");
            break;
           
            //if the file attribute is temporary
        case FILE_ATTRIBUTE_TEMPORARY:
            printf( "T ");
            break;
           
            //if the file attribute is sparse file
        case FILE_ATTRIBUTE_SPARSE_FILE:
            printf( "SF ");
            break;
           
            //if the file attribute is reparse point
        case FILE_ATTRIBUTE_REPARSE_POINT:
            printf( "RP ");
            break;
           
            //if the file attribute is compressed
        case FILE_ATTRIBUTE_COMPRESSED:
            printf( "C ");
            break;
           
            //if the file attribute is offline
        case FILE_ATTRIBUTE_OFFLINE:
            printf( "O ");
            break;
        }
    }   
}
flyingfor's Avatar
Go4Expert Member
very nice !!!
alramesh's Avatar
Go4Expert Member
what is _getch(); i know getch only...
johnson.reddy's Avatar
Light Poster
atleast you have to give some comments on every functions.
shabbir's Avatar, Join Date: Jul 2004
Go4Expert Founder
Quote:
Originally Posted by johnson.reddy
atleast you have to give some comments on every functions.
Thats a very good suggestions.
imrantechi's Avatar, Join Date: Feb 2008
Ambitious contributor
when we use vc++ ,we write _getch instead of getch .

this is because, The POSIX name for getch is deprecated.

so we use the ISO C++ conformant name: _getch.

if we use getch ,we get a warning this is removed with the help of using _getch
debleena_doll2002's Avatar
Ambitious contributor
I required this assignment . Can you send me with some detail because whatever you posted that is not understandable As per told by johnson.reddy,
imrantechi's Avatar, Join Date: Feb 2008
Ambitious contributor
Quote:
Originally Posted by debleena_doll2002
I required this assignment . Can you send me with some detail because whatever you posted that is not understandable As per told by johnson.reddy,
ya i have realised i have missed the comments.

i will post the article back again with proper explanation.
imrantechi's Avatar, Join Date: Feb 2008
Ambitious contributor
Code: C
//Header Files
#include "filelist.h"

/**
 * main () this is used to receive path at the command line.
 *
 * @Param [in] argc contains the number of strings in a command prompt.
 *
 * @Param [in] *argv[] contains the address of the strings.
 *
 */


int main(int argc, char *argv[])
{
        char* DirSpec;  // pointer to a character declaration.

        int traversal; //variable declaration.

        char* substring; // pointer to a character declaration.

    argv[1]="c:";

    argv[2]="/s";

    argc=2;

    printf ("Target directory is %s.\n", argv[1]);

    DirSpec=(char*)calloc ( strlen(argv[1])+1,sizeof(char));    //memory allocation for the path.

    strcpy(DirSpec,argv[1]);        //copies the argv[1] to path.

    printf("Name \t\t\t\t Dir/Size \t Created \t     Attributes");

    if(strcmp(argv[2],"/s")==0){

        traversal=INTERNALTRAVERSING;   //sets the traversal type to internal.

    }else{

        traversal=FIRSTLEVELTRAVERSING; //sets the traversal type to first level.

    }

    //checks if the path contains an extension.
    if(FindMatch(DirSpec)!=1){
       
        if(GetFileAttributes(DirSpec)==FILE_ATTRIBUTE_DIRECTORY){

            substring=NULL;

            strcat(DirSpec,"\\*");

        }else{

            substring=GetSubstring(DirSpec);    //retrieves the extensio of the path in a substring.
        }

    }else{

        substring=NULL;
    }
       
    WalkFolder(DirSpec,traversal,substring);    //calls  the walk folder with path,traversal type and extension.   

    _getch();

    free(DirSpec);              //frees the memory allocated for path.

    return (0);

}

/**
 * Display(WIN32_FIND_DATA *pFindFileData) () is used to display the details of the file or folder.
 *
 * @Param [in]  *pFindFileData    contains the file data.
 *
 */


void Display(WIN32_FIND_DATA *pFindFileData)
{   
   
        LPSYSTEMTIME lpst;   

    lpst=(LPSYSTEMTIME)calloc(1,sizeof(SYSTEMTIME));    //allocates memory for lpst.

    FileTimeToSystemTime(&pFindFileData->ftCreationTime,lpst); //converts the time to system time.

    if(pFindFileData->nFileSizeLow==0)

        printf ("\n %s \t\t\t\t <Dir>\t\t ", pFindFileData->cFileName);
   
    else

        printf("\n %s \t %d \t ",pFindFileData->cFileName,pFindFileData->nFileSizeLow);

        printf("%d/%d/%d %d:%d:%d \t ",lpst->wDay,lpst->wMonth,lpst->wYear,lpst->wHour,lpst->wMinute,lpst->wSecond);                       
        PrintFileAttribute(pFindFileData->dwFileAttributes);
       
        free(lpst);   //frees the memory allocated for lpst.

}

/**
 * WalkFolder (char* pPath,BOOL pSub_folders,char* pSubstr)() used to insert an integer into the specified stack.
 *
 * @Param [in]  pValue    contains the value which is to be pushed into the buffer.
 *
 * @Return    int            0 when pop fails else the element which was poped out.
 */


void WalkFolder (char* pPath,BOOL pSub_folders,char* pSubstr)
{
        WIN32_FIND_DATA FindFileData;

        HANDLE hFind;         //contains the handle returned by the path.

        DWORD dwError;      //contains the last error occurred.

        char ** allpath;        //pointer to the array which stores all new paths.

        int index=0;            //contains the total count of paths stored.

        int i;          //used for looping.

        static int no_of_files=0;   //contains the number of files.

        static int no_of_folders=0//contains the number of folders.

    printf("\n .................................................................");

    printf("\n The display is for the path %s \n ", pPath);

    allpath=(char **)calloc(DEFAULTSIZE,sizeof(char*));  //allocates memory for allpath.

    hFind= INVALID_HANDLE_VALUE;        //assigness invalid handle value to hFind.

    hFind = FindFirstFile(pPath, &FindFileData);    //assigns the first file handle to hFind.

    if (hFind == INVALID_HANDLE_VALUE && pSub_folders!=INTERNALTRAVERSING ) {

        printf ("Invalid file handle. Error is %u\n", GetLastError());
       

    } else if(hFind!= INVALID_HANDLE_VALUE && pSubstr !=NULL){
   
        PrintFileInfo(hFind,&FindFileData,&no_of_files);
       
    }

    if(pSubstr !=NULL && pSub_folders==INTERNALTRAVERSING){

       RemoveSubString(pPath,pSubstr)//calls RemoveSubString function to remove the extension from it.

       hFind = FindFirstFile(pPath, &FindFileData)//assigns the first file handle to hFind.

     }

     do{

        if(pSubstr==NULL){

            Display(&FindFileData);  //calls the display function to print the file and folder details.

        }

        if(FindFileData.nFileSizeLow==0 && (strcmp(FindFileData.cFileName,".")!=0)
         && (strcmp(FindFileData.cFileName,"..")!=0)&& pSub_folders==INTERNALTRAVERSING){
    
            if((index+1)%DEFAULTSIZE==0 && index>0){
            
                allpath=(char **)realloc(allpath,(index+DEFAULTSIZE))//reallocates memory.

            }
            allpath[index]=GetNewPath(pPath,FindFileData.cFileName,pSubstr);    //retrieves the new path and stores it                                            in allpath.
            index++;

        }else if(FindFileData.nFileSizeLow!=0 && pSubstr==NULL){

            no_of_files++;    //increments the number of files

        }if(FindFileData.nFileSizeLow==0 ){
   
            no_of_folders++;    //increments the number of folders.
        }
   
       }while (FindNextFile(hFind, &FindFileData) != 0 );   //works until  next file exists.

 
    for(i=0;i<index;i++){

        WalkFolder(allpath[i],pSub_folders,pSubstr);    //calls back the walk folder with the new path.
    }

    dwError = GetLastError();   //stores the last error

    FindClose(hFind);   //closes the file opened,whose handle is passed.

    if (dwError != ERROR_NO_MORE_FILES) {

        printf ("FindNextFile error. Error is %u\n", dwError)//prints the error message.
       
    }
      
   
}

/**
 * GetNewPath(char* pPath,char *pFileName,char* pType)() used to retrieve the path for internal traversing.
 *
 * @Param [in]  pPath contains the path from which new path is to be retrieved.
 *
 * @Param [in]  pFileName contains the file from which new path is to be retrieved.
 *
 * @Param [in]  pType contains a substring ,if the path is of specific type,else NULL.
 *
 * @Return    char*   returns the new path.
 */


char * GetNewPath(char* pPath,char *pFileName,char* pType)
{

        char* path;   //contains the new path.

        if(pType==NULL){
       
            path=(char*)calloc(strlen(pPath)+strlen(pFileName)+1,sizeof(char))//memory allocation for path ,if there                                                                  is no extension.

        }else{

            path=(char*)calloc(strlen(pPath)+strlen(pFileName)+strlen(pType)+1,sizeof(char));//memory allocation for                                                                                                path ,if there is extension.

        }

    strcpy(path,pPath);     //copies the previous sent path to path.

    path[strlen(path)-1]='\0';      //adds a '\0' at the end of the path.

    strcat(path,pFileName);    //adds the filename to the path.

    if(pType==NULL){

        strcat(path,"\\*");    //adds \* if there is no extension.

    }else{

        strcat(path,pType);    //adds the extension at the back of the path.
    }

    return path;                        //returns the path .

}

/**
 * FindMatch(char* pPath)() used to find aparticular match pattern in the string.
 *
 * @Param [in]  pPath contains the path from which match is to be found.
 *
 * @Return    int   returns true if match is found,else false.
 */


int FindMatch(char* pPath)
{
    int i;

    i=strlen(pPath)-1;    //calculates the length of the path

    if(pPath[i]=='*'&& pPath[i-1]=='\\'){   //checks if the path contains \*

            return TRUE;                //returns true if \* is found.
    }

    return FALSE;         //returns false if \* not found.
}

/**
 * GetSubstring(char* pPath)() used to get the extension of the path as substring.
 *
 * @Param [in]  pPath contains the path for which extension is to be found.
 *
 * @Return    char*  returns the substring.
 */


char* GetSubstring(char* pPath)
{

        char* substring;   //contains the substring i.e the extension.

        int i;        //used for looping.

        int length;   //contains the length for the extension.

    for(i=strlen(pPath)-1;i>0;i--){
   
        if(pPath[i]=='\\')    //checks for first \ from back and breaks.
            break;
    }

    length=strlen(pPath)+1-i;      //calculates the length of the extension.

    substring=(char*)calloc(length,sizeof(char));   //allocates memory for the substring.

    strcpy(substring,(pPath+i));        //copies the extension to substring.

    return substring;         //returns the extension.
}

/**
 * RemoveSubString(char *pPath,char* pSubstr)() used to remove the substring from the path.
 *
 * @Param [in]  pPath contains the path for which extension is to be removed.
 *
 * @Param [in]  pSubstr   contains the extension which is to be removed.
 *
 */


void RemoveSubString(char *pPath,char* pSubstr)
{
       
        int len;                //contains the length of the path without extension.

    len=strlen(pPath)-strlen(pSubstr)+4;    //calculates the new length.

    pPath=(char*)realloc(pPath,(len));    //reallocates memory for path.
   
    pPath[len-4]='\0';          //appends a '\0' to end the path.

    strcat(pPath,"\\*.");            //adds a \. at then sn dof the path.

}

/**
 * PrintFileInfo(HANDLE hFind,WIN32_FIND_DATA *FindFileData,int *no_of_files)() used to print the file details.
 *                                     
 * @Param [in]  hFind contains the hanle of the file .
 *
 * @Param [in]  FindFileData  used to find the data about the file .
 *
 * @Param [in]  *no_of_files  contains the number of files .
 *
 */


void PrintFileInfo(HANDLE hFind,WIN32_FIND_DATA *FindFileData,int *no_of_files)
{

    do{
   
        Display(FindFileData)//calls the display function to print the file and folder details.

        *no_of_files++;  //calculates the number of files.
   
    }while(FindNextFile(hFind, FindFileData) != 0 );    //works until no more files are left.

}

/**
 * PrintFileAttribute(DWORD fileAttribute)() used to print the attributes of the file.
 *
 * @Param [in]  pFileattribute    contains the attributes of the file.
 *
 */


void PrintFileAttribute(DWORD   pFileattribute )
{
        int  index;               ///< holds the index of attribute array
        int  flag;                    ///< holds the flag value

        ///< attribute array holds the file all attributes
        int  attribute[12] = {FILE_ATTRIBUTE_READONLY,
                                    FILE_ATTRIBUTE_HIDDEN,
                                    FILE_ATTRIBUTE_SYSTEM,
                                    FILE_ATTRIBUTE_DIRECTORY,
                                    FILE_ATTRIBUTE_ARCHIVE,
                                    FILE_ATTRIBUTE_DEVICE,
                                    FILE_ATTRIBUTE_NORMAL,
                                    FILE_ATTRIBUTE_TEMPORARY,
                                    FILE_ATTRIBUTE_SPARSE_FILE,
                                    FILE_ATTRIBUTE_REPARSE_POINT,
                                    FILE_ATTRIBUTE_COMPRESSED,
                                    FILE_ATTRIBUTE_OFFLINE};

    //Assign starting value zero to count
    index =0;
    //printf("\t");

    //loop continue upto fileattribute greaterthan attribute[count]
    while (pFileattribute    >=(unsigned long) attribute[index]) {

        //flag holds attribute value
        flag = pFileattribute    & attribute[index++];
       
        switch (flag) {

            //if the file attribute is readonly
            case FILE_ATTRIBUTE_READONLY:
                printf( "R ");
                break;
            //if the file attribute is hidden
            case FILE_ATTRIBUTE_HIDDEN:
                printf( "H ");
                break;

            //if the file attribute is system
            case FILE_ATTRIBUTE_SYSTEM:
                printf( "S ");
                break;

            //if the file attribute is archive
            case FILE_ATTRIBUTE_ARCHIVE:
                printf( "A ");
                break;

            //if the file attribute is device
            case FILE_ATTRIBUTE_DEVICE:
                printf( "D ");
                break;

            //if the file attribute is normal
            case FILE_ATTRIBUTE_NORMAL:
                printf( "N ");
                break;

            //if the file attribute is temporary
            case FILE_ATTRIBUTE_TEMPORARY:
                printf( "T ");
                break;

            //if the file attribute is sparse file
            case FILE_ATTRIBUTE_SPARSE_FILE:
                printf( "SF ");
                break;

            //if the file attribute is reparse point
            case FILE_ATTRIBUTE_REPARSE_POINT:
                printf( "RP ");
                break;

            //if the file attribute is compressed
            case FILE_ATTRIBUTE_COMPRESSED:
                printf( "C ");
                break;

            //if the file attribute is offline
            case FILE_ATTRIBUTE_OFFLINE:
                printf( "O ");
                break;
        }
    }   
}

Last edited by imrantechi; 10Jul2008 at 14:43..
imrantechi's Avatar, Join Date: Feb 2008
Ambitious contributor
i think now you will be able to understand