Get File details recursively for all folder in directory Windows

Get File details recursively for all folder in directory Windows

Following example retrieves details like  file name ,Size ,last Write Time ,last Access Time ,creationTime , file attributes , extention ,file Path :
ofstream myfile;
void listDir(const char * dirn)
{
char dirnPath[1024];
string ext
;
sprintf
(dirnPath, “%s\\*”, dirn);

WIN32_FIND_DATA f;
HANDLE h
= FindFirstFile(dirnPath, &f);

if (h == INVALID_HANDLE_VALUE) { return; }

do
{
const char * name = f.cFileName;

if (strcmp(name, “.”) == 0 || strcmp(name, “..”) == 0) { continue; }

char filePath[1024];
sprintf
(filePath, “%s%s%s”, dirn, “\\”, name);

if (f.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
{
listDir
(filePath);
}
else
{
string filename
=filePath;
const size_t last_slash_idx = filename.find_last_of(“\\/”);
if (std::string::npos != last_slash_idx)
{
filename
.erase(0, last_slash_idx + 1);
}

// Get extension if present.
const size_t period_idx = filename.rfind(‘.’);
if (std::string::npos != period_idx)
{
ext
=filename.substr(period_idx,filename.length()-1);
}

// Retrieve owner name of the file
DWORD d;
WIN32_FILE_ATTRIBUTE_DATA fileInfo
;

DWORD dwRtnCode = 0;
HANDLE hFile
=CreateFile(filePath,
GENERIC_READ
,
FILE_SHARE_READ
,
NULL
,
OPEN_EXISTING
,
FILE_ATTRIBUTE_NORMAL
,
NULL
);
PSID pSidOwner
= NULL;
PSECURITY_DESCRIPTOR pSD
= NULL;
dwRtnCode
= GetSecurityInfo(
hFile
,
SE_FILE_OBJECT
,
OWNER_SECURITY_INFORMATION
,
&pSidOwner,
NULL
,
NULL
,
NULL
,
&pSD);
if (dwRtnCode != ERROR_SUCCESS) {
DWORD dwErrorCode
= 0;

dwErrorCode = GetLastError();
_tprintf
(TEXT(“GetSecurityInfo error = %d\n”), dwErrorCode);

}

// First call to LookupAccountSid to get the buffer sizes.
BOOL bRtnBool
= TRUE;
LPTSTR
AcctName = NULL;
LPTSTR
DomainName = NULL;
DWORD dwAcctName
= 1, dwDomainName = 1;
SID_NAME_USE eUse
= SidTypeUnknown;
bRtnBool
= LookupAccountSid(
NULL
, // local computer
pSidOwner
,
AcctName,
(LPDWORD)&dwAcctName,
DomainName,
(LPDWORD)&dwDomainName,
&eUse);
// Reallocate memory for the buffers.
AcctName = (LPTSTR)GlobalAlloc(
GMEM_FIXED
,
dwAcctName
);
// Check GetLastError for GlobalAlloc error condition.
if (AcctName == NULL) {
DWORD dwErrorCode
= 0;

dwErrorCode = GetLastError();
_tprintf
(TEXT(“GlobalAlloc error = %d\n”), dwErrorCode);

}

DomainName = (LPTSTR)GlobalAlloc(
GMEM_FIXED
,
dwDomainName
);

// Check GetLastError for GlobalAlloc error condition.
if (DomainName == NULL) {
DWORD dwErrorCode
= 0;

dwErrorCode = GetLastError();
_tprintf
(TEXT(“GlobalAlloc error = %d\n”), dwErrorCode);

}

// Second call to LookupAccountSid to get the account name.
bRtnBool
= LookupAccountSid(
NULL
, // name of local or remote computer
pSidOwner
, // security identifier
AcctName, // account name buffer
(LPDWORD)&dwAcctName, // size of account name buffer
DomainName, // domain name
(LPDWORD)&dwDomainName, // size of domain name buffer
&eUse); // SID type

// Check GetLastError for LookupAccountSid error condition.
if (bRtnBool == FALSE) {
DWORD dwErrorCode
= 0;

dwErrorCode = GetLastError();

if (dwErrorCode == ERROR_NONE_MAPPED)
{
_tprintf
(TEXT
(“Account owner not found for specified SID.\n”));
AcctName=“Could Not Extract”;
}
else
_tprintf
(TEXT(“Error in LookupAccountSid.\n”));

}
else if (bRtnBool == TRUE)
{
// AcctName is owner name , print it
}

if(GetFileAttributesEx(filePath, GetFileExInfoStandard, &fileInfo))
{
// get size of the file
int nSize = fileInfo.nFileSizeLow;
SYSTEMTIME st
;
// get creation time of file FileTimeToSystemTime(&fileInfo.ftCreationTime,&st);
DWORD
// get file attributes like hidden etc.
attr
=fileInfo.dwFileAttributes;

string creationTime= “”;
CString cstrMessage;

cstrMessage.Format( “%d-%02d-%02d %02d:%02d:%02d.%03d”,
st
.wYear,
st
.wMonth,
st
.wDay,
st
.wHour,
st
.wMinute,
st
.wSecond,
st
.wMilliseconds );
creationTime
=cstrMessage;

SYSTEMTIME st1;
// get last access time of file FileTimeToSystemTime(&fileInfo.ftLastAccessTime,&st1);
string lastAccessTime
= “”;
CString cstrMessage1;

cstrMessage1.Format( “%d-%02d-%02d %02d:%02d:%02d.%03d”,
st1
.wYear,
st1
.wMonth,
st1
.wDay,
st1
.wHour,
st1
.wMinute,
st1
.wSecond,
st1
.wMilliseconds );
lastAccessTime
=cstrMessage1;

SYSTEMTIME st2;
// get last modified time of file FileTimeToSystemTime(&fileInfo.ftLastWriteTime,&st2);
string lastWriteTime
= “”;
CString cstrMessage2;

cstrMessage2.Format( “%d-%02d-%02d %02d:%02d:%02d.%03d”,
st2
.wYear,
st2
.wMonth,
st2
.wDay,
st2
.wHour,
st2
.wMinute,
st2
.wSecond,
st2
.wMilliseconds );
lastWriteTime
=cstrMessage2;

// cout << “File size=” << nSize << ” “ << creationTime << ” “ << lastAccessTime << ” “ <<lastWriteTime << endl;

myfile << filename << “|” << nSize << “|” << lastWriteTime << “|” << lastAccessTime << “|” << creationTime << “|” << AcctName << “|” << attr << “|” << ext << “|” <<filePath <<“\n”;

}
else
cout
<< “file not found”;
}
} while (FindNextFile(h, &f));
FindClose(h);
}

int main()
{
try{

myfile.open (“output.csv”,std::fstream::app);
listDir
(“C:\\Users\\nUser\\Desktop”);
myfile
.close();
}
catch(exception e)
{
std
::cerr << “exception caught: “ << e.what() << ‘\n’;

}
getch
();
}

Further try following code using dirent .h  :
#include<stdio.h>
#include<sys/types.h>
#include<dirent.h>
#include<string.h>
#include <iostream>
using namespace std;

struct dirent *drnt;
int main() {

DIR *dir;
struct dirent *dp;
char * file_name;
char dirpath [100] ;

while(1==1){
// printf(“Choose dir:”);
// scanf(“%s”,dirpath);
dir
= opendir(“C:\\Users\\tarun.s\\Desktop”);
while ((dp=readdir(dir)) != NULL) {
if ( !strcmp(dp->d_name, “.”) || !strcmp(dp->d_name, “..”) )
{
// do nothing (straight logic)
} else {
file_name
= dp->d_name; // use it
printf
(“file_name: \”%s\”\n”,file_name);
}
}
closedir
(dir);
}

return 0;

}

Call command dir from C program — This is bit faster but the output would require a lot of formatting and you  get 4 columns only(size , owner ,File Name, Modified Date)  .Comand used is

dir /q /s /tc /a-d /O:D /T:W

Following solutions could be tried for speeding up the output:

1.      That is the fastest approach you can come across(Approach 1 ). Also you may consider using another thread to manage directory enumerations as it takes a lot of time. even Microsoft file explorer spend some time if the directory has a lot of sub folders/files.

2.      A faster approach would be to bypass the FindFirstFile...() API and go straight to the file system directly. You can use DeviceIoControl() with the FSCTL_ENUM_USN_DATA control to access the master file table, at least on NTFS formatted volumes. With that information, you can directly access the records for files/folders, which includes their attributes, parent info, etc. Yes, it would be more work, but it should also be faster since you can optimize the code to access just the pieces you need.

A utility is already there which does get recursively details of all files in a folder/subfolder which is FileList developed by Jam Software which can be downloaded here:

http://filelist.en.softonic.com/

Resolving technical problems:

Solve your technical problems instantly

We provide Remote Technical Support from Monday to Sunday, 7:00PM to 1:00 AM

Mail your problem details at writeulearn@gmail.com along with your mobile numberand we will give you a call for further details. We usually attend your problems within 60 minutes and solve it in maximum 2 days.

Leave a Reply

Your email address will not be published. Required fields are marked *