From: jmichae3 on
I need some working code that walks a directory tree and (at least)
prints out the full path of every file. it must work on windows 2000/
xp/vista, and (hopefully) windows 9x.

Is there a possibility of getting both dirent.h code for Borland C++
5.5 and (at the least) win32 code using FindFirstFile/FindNextFile/
FindClose?

I have not been able to find any working good examples.

Here's what I have:

I keep trying, but I never seem to quite get the directory recursion
thing down on windows 2000/xp. I get strange results.
C:\prj\zapdupes\zapdupes-1.0\win>dir/s/b
C:\prj\zapdupes\zapdupes-1.0\win\testdir\a\
C:\prj\zapdupes\zapdupes-1.0\win\testdir\b\
C:\prj\zapdupes\zapdupes-1.0\win\testdir\z
C:\prj\zapdupes\zapdupes-1.0\win\testdir\a\a
C:\prj\zapdupes\zapdupes-1.0\win\testdir\a\b
C:\prj\zapdupes\zapdupes-1.0\win\testdir\a\c
C:\prj\zapdupes\zapdupes-1.0\win\testdir\b\a
C:\prj\zapdupes\zapdupes-1.0\win\testdir\b\b
C:\prj\zapdupes\zapdupes-1.0\win\testdir\b\c
C:\prj\zapdupes\zapdupes-1.0\win>zapdupes testdir
md5 "testdirz"=d41d8cd98f00b204e9800998ecf8427e

C:\prj\zapdupes\zapdupes-1.0\win>zapdupes .\testdir
md5 ".\testdirz"=d41d8cd98f00b204e9800998ecf8427e

C:\prj\zapdupes\zapdupes-1.0\win>zapdupes c:\prj\zapdupes
\zapdupes-1.0\win\testd
ir
md5 "c:\prj\zapdupes\zapdupes-1.0\win
\testdirz"=d41d8cd98f00b204e9800998ecf8427e


C:\prj\zapdupes\zapdupes-1.0\win>zapdupes c:\prj\zapdupes
\zapdupes-1.0\win\testd
ir\
md5 "c:\prj\zapdupes\zapdupes-1.0\win\testdir
\z"=ef86d6e78171dddbf5895438933d73f
b
md5 "c:\prj\zapdupes\zapdupes-1.0\win\testdir\a
\a"=3f2349eb8a9c0e80edc08e734b7ef
04b
md5 "c:\prj\zapdupes\zapdupes-1.0\win\testdir\a
\b"=f1d27b05745dbcd976c488f9730d2
b2a
md5 "c:\prj\zapdupes\zapdupes-1.0\win\testdir\a
\c"=45a6123cac46f5a8cd432bfad2102
dcd
md5 "c:\prj\zapdupes\zapdupes-1.0\win\testdir\b
\a"=0de363bdf864da1730f7ebe5a1c59
ff7
md5 "c:\prj\zapdupes\zapdupes-1.0\win\testdir\b
\b"=b8d9890b068dce28b17dda5541943
b86
md5 "c:\prj\zapdupes\zapdupes-1.0\win\testdir\b
\c"=c5a8a899e66df8c89844d265ca42f
cf8

Notice it does not recurse into subdirectories unless the full path is
specified and a \ is on the end I thought I took care of that with
appendBackslashIfNone.

//danger! only use this routine on strings that have enough space
// allocated for the extra character!
void appendBackslashIfNone(char * str) {
int l = strlen(str);
if (l > 0 && str[l-1]!='\\') {
str[l]='\\';
str[l+1]='\0';
}
}


//no copyright notice given, but I am putting one here nonetheless.
//function Copyright 2000 Michael D. Ober, modified by Jim Michaels
void addTreeToList(const char *root, md5list * plist)
{
HANDLE hRoot;
WIN32_FIND_DATA fdRoot;
char fRoot[MAX_PATH];
char branch[MAX_PATH];
vector<string> dirs;
vector<string>::iterator it;

strcpy(fRoot, root);
appendBackslashIfNone(fRoot);
strcat(fRoot, "*.*");

hRoot = FindFirstFile(fRoot, &fdRoot);
if (hRoot == INVALID_HANDLE_VALUE)
return;

do {
strcpy(branch, root);
strcat(branch, fdRoot.cFileName);
if (fdRoot.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
if ((strcmp(fdRoot.cFileName, ".") != 0) &&
(strcmp(fdRoot.cFileName, "..") != 0)) {
// Subdir found
strcat(branch, "\\");
string s=branch;
dirs.push_back(s);
}
} else { // We have a file
// printf("DEL: %s\n", branch);
// DeleteFile(branch);
string s_md5;
string s_filepath;
s_filepath=branch;
// s_filepath=fd.cFileName;
//calc md5
printf("md5 \"%s\"=", branch);
// printf("md5 \"%s\"=", fd.cFileName);
ifstream infile(branch);
// ifstream infile(fd.cFileName);
//MD5 * md5 = new MD5();
s_md5 = getMD5(infile);
printf("%s\n", s_md5.c_str());
//delete md5;
//add to list
plist->putMd5AndDir(s_md5, s_filepath);
}
} while (FindNextFile(hRoot, &fdRoot));
FindClose(hRoot);
//printf("RD: %s\n", root);
//RemoveDirectory(root);
for (it=dirs.begin(); it!=dirs.end();it++) {
addTreeToList(it->c_str(), plist);
}
}
From: jmichae3 on
On Jul 2, 10:41 pm, jmich...(a)yahoo.com wrote:
> I need some working code that walks a directory tree and (at least)
> prints out the full path of every file.  it must work on windows 2000/
> xp/vista, and (hopefully) windows 9x.
>
> Is there a possibility of getting both dirent.h code for Borland C++
> 5.5 and (at the least) win32 code using FindFirstFile/FindNextFile/
> FindClose?
>
> I have not been able to find any working good examples.
>
> Here's what I have:
>
> I keep trying, but I never seem to quite get the directory recursion
> thing down on windows 2000/xp.  I get strange results.
> C:\prj\zapdupes\zapdupes-1.0\win>dir/s/b
> C:\prj\zapdupes\zapdupes-1.0\win\testdir\a\
> C:\prj\zapdupes\zapdupes-1.0\win\testdir\b\
> C:\prj\zapdupes\zapdupes-1.0\win\testdir\z
> C:\prj\zapdupes\zapdupes-1.0\win\testdir\a\a
> C:\prj\zapdupes\zapdupes-1.0\win\testdir\a\b
> C:\prj\zapdupes\zapdupes-1.0\win\testdir\a\c
> C:\prj\zapdupes\zapdupes-1.0\win\testdir\b\a
> C:\prj\zapdupes\zapdupes-1.0\win\testdir\b\b
> C:\prj\zapdupes\zapdupes-1.0\win\testdir\b\c
> C:\prj\zapdupes\zapdupes-1.0\win>zapdupes testdir
> md5 "testdirz"=d41d8cd98f00b204e9800998ecf8427e
>
> C:\prj\zapdupes\zapdupes-1.0\win>zapdupes .\testdir
> md5 ".\testdirz"=d41d8cd98f00b204e9800998ecf8427e
>
> C:\prj\zapdupes\zapdupes-1.0\win>zapdupes c:\prj\zapdupes
> \zapdupes-1.0\win\testd
> ir
> md5 "c:\prj\zapdupes\zapdupes-1.0\win
> \testdirz"=d41d8cd98f00b204e9800998ecf8427e
>
> C:\prj\zapdupes\zapdupes-1.0\win>zapdupes c:\prj\zapdupes
> \zapdupes-1.0\win\testd
> ir\
> md5 "c:\prj\zapdupes\zapdupes-1.0\win\testdir
> \z"=ef86d6e78171dddbf5895438933d73f
> b
> md5 "c:\prj\zapdupes\zapdupes-1.0\win\testdir\a
> \a"=3f2349eb8a9c0e80edc08e734b7ef
> 04b
> md5 "c:\prj\zapdupes\zapdupes-1.0\win\testdir\a
> \b"=f1d27b05745dbcd976c488f9730d2
> b2a
> md5 "c:\prj\zapdupes\zapdupes-1.0\win\testdir\a
> \c"=45a6123cac46f5a8cd432bfad2102
> dcd
> md5 "c:\prj\zapdupes\zapdupes-1.0\win\testdir\b
> \a"=0de363bdf864da1730f7ebe5a1c59
> ff7
> md5 "c:\prj\zapdupes\zapdupes-1.0\win\testdir\b
> \b"=b8d9890b068dce28b17dda5541943
> b86
> md5 "c:\prj\zapdupes\zapdupes-1.0\win\testdir\b
> \c"=c5a8a899e66df8c89844d265ca42f
> cf8
>
> Notice it does not recurse into subdirectories unless the full path is
> specified and a \ is on the end  I thought I took care of that with
> appendBackslashIfNone.
>
> //danger!  only use this routine on strings that have enough space
> //         allocated for the extra character!
> void appendBackslashIfNone(char * str) {
>     int l = strlen(str);
>     if (l > 0 && str[l-1]!='\\') {
>         str[l]='\\';
>         str[l+1]='\0';
>     }
>
> }
>
> //no copyright notice given, but I am putting one here nonetheless.
> //function Copyright 2000 Michael D. Ober, modified by Jim Michaels
> void addTreeToList(const char *root, md5list * plist)
> {
>     HANDLE hRoot;
>     WIN32_FIND_DATA fdRoot;
>     char fRoot[MAX_PATH];
>     char branch[MAX_PATH];
>     vector<string> dirs;
>     vector<string>::iterator it;
>
>     strcpy(fRoot, root);
>     appendBackslashIfNone(fRoot);
>     strcat(fRoot, "*.*");
>
>     hRoot = FindFirstFile(fRoot, &fdRoot);
>     if (hRoot == INVALID_HANDLE_VALUE)
>         return;
>
>     do {
>         strcpy(branch, root);
>         strcat(branch, fdRoot.cFileName);
>         if (fdRoot.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
>             if ((strcmp(fdRoot.cFileName, ".") != 0) &&
>                   (strcmp(fdRoot.cFileName, "..") != 0)) {
>                  // Subdir found
>                  strcat(branch, "\\");
>                  string s=branch;
>                  dirs.push_back(s);
>             }
>         } else { // We have a file
> //            printf("DEL: %s\n", branch);
> //            DeleteFile(branch);
>             string s_md5;
>             string s_filepath;
>             s_filepath=branch;
> //            s_filepath=fd.cFileName;
>             //calc md5
>             printf("md5 \"%s\"=", branch);
> //            printf("md5 \"%s\"=", fd.cFileName);
>             ifstream infile(branch);
> //            ifstream infile(fd.cFileName);
>             //MD5 * md5 = new MD5();
>             s_md5 = getMD5(infile);
>             printf("%s\n", s_md5.c_str());
>             //delete md5;
>             //add to list
>             plist->putMd5AndDir(s_md5, s_filepath);
>         }
>     } while (FindNextFile(hRoot, &fdRoot));
>     FindClose(hRoot);
>     //printf("RD:  %s\n", root);
>     //RemoveDirectory(root);
>     for (it=dirs.begin(); it!=dirs.end();it++) {
>         addTreeToList(it->c_str(), plist);
>     }
>
> }

fixed that code. now on to other bugs. here's the fixed code.

//danger! only use this routine on strings that have enough space
// allocated for the extra character!
void appendBackslashIfNone(char * str) {
int l = strlen(str);
if (l > 0 && str[l-1]!='\\') {
str[l]='\\';
str[l+1]='\0';
}
}


//no copyright notice given, but I am putting one here nonetheless.
//function Copyright 2000 Michael D. Ober, modified by Jim Michaels
void addTreeToList(const char *root, md5list * plist)
{
HANDLE hRoot;
WIN32_FIND_DATA fdRoot;
char fRoot[MAX_PATH];
char branch[MAX_PATH];
vector<string> dirs;
vector<string>::iterator it;

strcpy(fRoot, root);
appendBackslashIfNone(fRoot);
strcat(fRoot, "*.*");

hRoot = FindFirstFile(fRoot, &fdRoot);
if (hRoot == INVALID_HANDLE_VALUE)
return;

do {
strcpy(branch, root);
appendBackslashIfNone(branch);
strcat(branch, fdRoot.cFileName);
if (fdRoot.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
if ((strcmp(fdRoot.cFileName, ".") != 0) &&
(strcmp(fdRoot.cFileName, "..") != 0)) {
// Subdir found
strcat(branch, "\\");
string s=branch;
dirs.push_back(s);
}
} else { // We have a file
// printf("DEL: %s\n", branch);
// DeleteFile(branch);
string s_md5;
string s_filepath;
s_filepath=branch;
// s_filepath=fd.cFileName;
//calc md5
printf("md5 \"%s\"=", branch);
// printf("md5 \"%s\"=", fd.cFileName);
ifstream infile(branch);
// ifstream infile(fd.cFileName);
//MD5 * md5 = new MD5();
s_md5 = getMD5(infile);
printf("%s\n", s_md5.c_str());
//delete md5;
//add to list
plist->putMd5AndDir(s_md5, s_filepath);
}
} while (FindNextFile(hRoot, &fdRoot));
FindClose(hRoot);
//printf("RD: %s\n", root);
//RemoveDirectory(root);
for (it=dirs.begin(); it!=dirs.end();it++) {
addTreeToList(it->c_str(), plist);
}
}
From: jmichae3 on
well, I have windows code, still need dirent code for Borland C++
5.5.
codegear.com has nothing on their site about this subject. search for
opendir and see what happens. nothing.
From: Christian ASTOR on
On 3 juil, 07:41, jmich...(a)yahoo.com wrote:
> I need some working code that walks a directory tree and (at least)
> prints out the full path of every file.  it must work on windows 2000/
> xp/vista, and (hopefully) windows 9x.

e.g. =>

(I didn't display full path, because it's not very readable)

...
(#define UNICODE)
WalkDir(L"C:\\foo");
...

DWORD WalkDir(WCHAR *pwszDir)
{
DWORD dwError = ERROR_SUCCESS;
WIN32_FIND_DATA fd;
HANDLE hFile;
WCHAR szPath[MAX_PATH], szFileName[MAX_PATH];
lstrcpy (szPath, pwszDir);
lstrcat (szPath, TEXT("\\*.*"));
hFile = FindFirstFile((LPCWSTR)szPath, &fd);
if (hFile != INVALID_HANDLE_VALUE)
{
wprintf(L"Directory : %s\n", pwszDir);
do
{
lstrcpy (szFileName, fd.cFileName);
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
lstrcat (szFileName, TEXT(" <DIR>"));
wprintf(L"%s\n", szFileName);
} while (FindNextFile(hFile, &fd));
}
FindClose(hFile);
hFile = FindFirstFile((LPCWSTR)szPath, &fd);
if (hFile != INVALID_HANDLE_VALUE)
{
do
{
if (!lstrcmp(fd.cFileName, L".") || !lstrcmp(fd.cFileName,
L".."))
continue;
lstrcpy (szPath, pwszDir);
lstrcat (szPath, TEXT("\\"));
lstrcat (szPath, fd.cFileName);
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if (fd.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
continue;
dwError = WalkDir(szPath);
if (dwError != ERROR_SUCCESS)
{
FindClose(hFile);
return dwError;
}
}
} while (FindNextFile(hFile, &fd));
}
FindClose(hFile);
return dwError;
}
From: Jerry Coffin on
In article <fe2fdd76-60e1-4d8b-828d-
f3d639ba4afb(a)q24g2000prf.googlegroups.com>, jmichae3(a)yahoo.com says...
> I need some working code that walks a directory tree and (at least)
> prints out the full path of every file. it must work on windows 2000/
> xp/vista, and (hopefully) windows 9x.
>
> Is there a possibility of getting both dirent.h code for Borland C++
> 5.5 and (at the least) win32 code using FindFirstFile/FindNextFile/
> FindClose?
>
> I have not been able to find any working good examples.

Here's how I do it. This is a bit different from most in doing a
breadth-first instead of depth-first traversal. Sometimes it helps quite
a bit, others it makes almost no difference (but it's rarely if ever any
slower than a depth-first traversal). A queue would work fine where I've
used a priority_queue, but this way the output is always sorted.

#pragma warning(disable:4786)
#include <windows.h>
#include <queue>
#include <sstream>
#include <iostream>
#include <algorithm>

// I think MS's names for some things are obnoxious.
const HANDLE HNULL = INVALID_HANDLE_VALUE;
const int A_DIR = FILE_ATTRIBUTE_DIRECTORY;

void process(std::string name) {
std::cout << name << std::endl;
}

void PrintFolder(std::string const &folder_name,
std::string const &fmask)
{
HANDLE finder; // for FindFirstFile
WIN32_FIND_DATA file; // data about current file.
std::priority_queue<std::string,
std::vector<std::string>,
std::greater<std::string>
> dirs;
dirs.push(folder_name); // start with passed directory

do {
std::string path = dirs.top();// retrieve directory to search
dirs.pop();

if (path[path.size()-1] != '\\') // normalize the name.
path += "\\";

std::string mask = path + fmask; // create mask for searching

// traverse a directory.
if (HNULL==(finder=FindFirstFile(mask.c_str(), &file))) {
continue;
}
do {
if (!(file.dwFileAttributes & A_DIR)) // print file names
process(path + file.cFileName);
} while (FindNextFile(finder, &file));
FindClose(finder);
if (HNULL==(finder=FindFirstFile((path + "*").c_str(), &file)))
continue;
do {
if ((file.dwFileAttributes & A_DIR) &&
(file.cFileName[0] != '.'))
{
dirs.push(path + file.cFileName);
}
} while (FindNextFile(finder, &file));
FindClose(finder);
} while (!dirs.empty());
}

int main() {
PrintFolder("C:\\", "*");
return 0;
}

--
Later,
Jerry.

The universe is a figment of its own imagination.