[obtain all file names in the specified directory]

1. Under linux environment

1.1 introduction to related functions

In Linux environment, < dirent h> Is an application program interface, which is mainly used for directory reading operation of file system, and provides several directory data reading functions.

Under Linux, all file name information can be obtained by traversing the folder by calling opendir, readdir and closedir. The declarations of the three functions are as follows:

/* Open a directory stream on NAME.
   Return a DIR stream on the directory, or NULL if it could not be opened.

   This function is a possible cancellation point and therefore not
   marked with __THROW.  */
extern DIR *opendir (const char *__name) __nonnull ((1));

/* Read a directory entry from DIRP.  Return a pointer to a `struct
   dirent' describing the entry, or NULL for EOF or error.  The
   storage returned may be overwritten by a later readdir call on the
   same DIR stream.

   If the Large File Support API is selected we have to use the
   appropriate interface.

   This function is a possible cancellation point and therefore not
   marked with __THROW.  */

extern struct dirent *readdir (DIR *__dirp) __nonnull ((1));

/* Close the directory stream DIRP.
   Return 0 if successful, -1 if not.

   This function is a possible cancellation point and therefore not
   marked with __THROW.  */
extern int closedir (DIR *__dirp) __nonnull ((1));

DIR structure definition

struct __dirstream   
{   
    void *__fd;    
    char *__data;    
    int __entry_data;    
    char *__ptr;    
    int __entry_ptr;    
    size_t __allocation;    
    size_t __size;    
    __libc_lock_define (, __lock)    
};   
typedef struct __dirstream DIR;  

dirent structure definition

struct dirent
{
    long d_ino;                     
    off_t d_off;                    
    unsigned short d_reclen;        
    char d_name [NAME_MAX+1];       
}

1.2 application code

/**********************************************************************
* File name: listfilenames c
* File ID: None
* Content summary: recursively get all file names for a given directory
* Other notes: None
**********************************************************************/
#include <string.h>
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>

static DIR* dir;
#define _MAXPATH 1024
#define _MAXFILENAME 256
/****************************************************************
 * Function Description: get the file name under the specified path
 * Input parameter: dir - object of execution folder
 *          
 * Output parameter: iFileName - the file name of a file
 * Return value: 0 - execution succeeded - 1 - execution failed
 * Other notes: None
 ****************************************************************/
int getOneFileName(DIR *dir, char *iFileName)
{
    int ret = 0;
    struct dirent *ptr;

    if((ptr=readdir(dir)) != NULL)
    {
        if(strcmp(ptr->d_name,".")==0 || strcmp(ptr->d_name,"..")==0)    // current dir OR parrent dir
            ret = getOneFileName(dir, iFileName);
        else if(ptr->d_type == 8)    /// file
        {
            strcpy(iFileName, ptr->d_name);
        }
    }
    else
    {
        ret = -1; //read end
    }
    return ret;
}

int main(int argc, char* argv[])
{
    if(argc < 2)
    {
        printf("Error. Enter an folder for list filename...\n");
        return 0;
    }

    char* pInputFolderPath = argv[1];
    char FileName[_MAXFILENAME] = {0};
    char FullPathName[_MAXPATH] = {0};
    if((dir = opendir(pInputFolderPath)) == NULL) // opendir
    {
        printf("Error. Failed to open folder ...");
        return 0;
    }
    while(getOneFileName(dir, FileName)==0)
    {
        snprintf(FullPathName,sizeof(FullPathName)-1, "%s/%s", pInputFolderPath, FileName);
        printf("FileName: %s\n", FullPathName);
    }

    return 0;
}

Compile

gcc listFileNames.c -o listFileNames

Run

./listFileNames /home/nvidia

2. Under Windows Environment

2.1 configuring C + + environment under Windows

Reference link: compiling, running and debugging C/C + + using vscode on windows 10 - Zhihu (zhihu.com)

  1. Download mingw-w64

mingw series compilers are very good and mainstream c/c + + compilers, Download address.

        2. Unzip and add environment variables

Add the bin folder path at mingw64 to the environment variable

C:\mingw64\bin

        3. test

Enter the following command on the Windows terminal to test the gcc environment. The printed information will finally get the version information of gcc.

 gcc -v

gcc version 8.1.0 (x86_64-posix-seh-rev0, Built by MinGW-W64 project)

2.2 read all file names in the specified directory

Under Windows, traverse all files in the folder, using the header file io.h.

        1. When traversing the file, IO Provided in H_ finddata_t structure to save the information of the file

#define _finddata_t _finddata32_t
  struct _finddata32_t {
    unsigned attrib;            // File properties
    __time32_t time_create;     // Creation time
    __time32_t time_access;     // Last visit time
    __time32_t time_write;      // last write time
    _fsize_t size;                // file size
    char name[260];            // file name
  };

         2. Pass_ findfirst,_ findnext,_ findclose to complete the traversal of the folder, where_ Findfirst and_ FindText is a macro definition that points to two functions.

#define _findfirst _findfirst64i32
#define _findnext _findnext64i32

 _ The function of findfirst is defined as follows. The function is to find the first instance that meets the conditions.

The first parameter: Filename is a wildcard

The second parameter: FindData is used to store the currently found file information

#ifndef __CRT__NO_INLINE
  __CRT_INLINE intptr_t __cdecl _findfirst64i32(const char *_Filename,struct _finddata64i32_t *_FindData)
  {
    struct __finddata64_t fd;
    intptr_t ret = _findfirst64(_Filename,&fd);
    if (ret == -1) {
      memset(_FindData,0,sizeof(struct _finddata64i32_t));
      return -1;
    }
    _FindData->attrib=fd.attrib;
    _FindData->time_create=fd.time_create;
    _FindData->time_access=fd.time_access;
    _FindData->time_write=fd.time_write;
    _FindData->size=(_fsize_t) fd.size;
    strncpy(_FindData->name,fd.name,260);
    return ret;
  }
#endif /* __CRT__NO_INLINE */

Return value: IntPtr is returned if the search is successful_ A handle of type T, but the handle is not a pointer, but an int. If the lookup fails, - 1 is returned.

typedef int intptr_t;

_ The FindText function is used to find the next qualified instance in the handle.

The first parameter: FindHandle is the handle returned by the above function

The second parameter: FindData is the file information of the next handle instance

Return value: - 1 for search failure and 0 for success

#ifndef __CRT__NO_INLINE
  __CRT_INLINE int __cdecl _findnext64i32(intptr_t _FindHandle,struct _finddata64i32_t *_FindData)
  {
    struct __finddata64_t fd;
    int ret = _findnext64(_FindHandle,&fd);
    if (ret == -1) {
      memset(_FindData,0,sizeof(struct _finddata64i32_t));
      return -1;
    }
    _FindData->attrib=fd.attrib;
    _FindData->time_create=fd.time_create;
    _FindData->time_access=fd.time_access;
    _FindData->time_write=fd.time_write;
    _FindData->size=(_fsize_t) fd.size;
    strncpy(_FindData->name,fd.name,260);
    return ret;
  }
#endif /* __CRT__NO_INLINE */

_ The function of findclose function is to close the given handle, return 0 for success and - 1 for failure

  _CRTIMP int __cdecl _findclose(intptr_t _FindHandle);

2.3 application code

Based on a given directory path, traverse and print the internal file name.

#include <direct.h>
#include <io.h>
#include <stdio.h>

#define _MAXPATH 1024
#define _MAXFILENAME 256

int getOneFileName(char* pInputFolderPath, char* iFileName)
{
    int ret = 0;
    long handle = 0;
    struct _finddata_t fileInfo;
    char FullPathName[_MAXPATH] = {0};

    char szPath[_MAXPATH] = {0};
    memset(szPath, 0, sizeof(szPath));
    _snprintf(szPath, sizeof(szPath)-1, "%s\\*", pInputFolderPath);

    if ((handle=_findfirst(szPath, &fileInfo)) == -1) 
    {
        printf("Error. Failed to open folder ...");
        return 0;
    } 
    else
    {
        do{
            if (fileInfo.attrib &_A_SUBDIR) // It's a directory
            {
                if (fileInfo.name[0] != '.') // File name is not '.' Or '..' Time
                {
                    memset(szPath, 0, sizeof(szPath));
                    _snprintf(szPath, sizeof(szPath)-1,"%s\\%s", pInputFolderPath, fileInfo.name);
                    printf("directory: %s\n", szPath);

                    ret = getOneFileName(szPath, iFileName);   // Continue traversal
                }
            }
            else    // If the first entity is not a directory, the file is displayed
            {
                strcpy(iFileName, fileInfo.name);
                snprintf(FullPathName,sizeof(FullPathName)-1, "%s\\%s", pInputFolderPath, iFileName);
                printf("filename:%s\n", FullPathName);
            }
        }while (_findnext(handle, &fileInfo) == 0);
        
    }
    return ret;
}

int main(int argc, char* argv[])
{
    char* pInputFolderPath = ".";

    char szPath[_MAXPATH] = {0};
    memset(szPath, 0, sizeof(szPath));
    _snprintf(szPath, sizeof(szPath)-1, "%s\\*", pInputFolderPath);

    char FileName[_MAXFILENAME] = {0};
    char FullPathName[_MAXPATH] = {0};
    struct _finddata_t fileInfo;
    getOneFileName(pInputFolderPath, FileName);

    return 0;
}

Reference link: C + + traversing files in folders under Windows - Xiong's name - blog Garden (cnblogs.com)

Keywords: C Linux Windows

Added by trackz on Thu, 09 Dec 2021 13:13:36 +0200