/////////////////////////////////////////////////////////////// // // // nav.cpp - recursively walk directory tree // // ver 1.3 starting at a specified path // // // // Language: Visual C++, ver 5.0 // // Platform: Micron Dual Pentium 200, Windows NT 4.0 // // Application: CRI-OOD Project #1, S99 // // Author: Jim Fawcett, CST 2-187, (315) 443-3948 // // fawcett@ecs.syr.edu // // // /////////////////////////////////////////////////////////////// #include // standard output for test #include // output formatting #include "nav.h" using namespace std; //----< default dir name display function >-------------------- void defProc::dirsProc(const string &dirName) { cout << "\n " << dirName.c_str() << endl; } //----< default file data display function >------------------- void defProc:: fileProc(const fileInfo &fi) { fi.showData(cout); } // //----< save user's working directory >------------------------ navig::navig(defProc &DP) : dp(DP) { // save user's working directory char buffer[256]; GetCurrentDirectory( 256, buffer); userDir = buffer; } //----< restore user's working directory >--------------------- navig::~navig() { SetCurrentDirectory(userDir.c_str()); } //----< specify starting directory and initiate walk >--------- void navig::start(string dir) { // convert "." or ".." into full path name char buffer[256]; if( ( dir == "." ) || ( dir == ".." ) ) { if( !SetCurrentDirectory( dir.c_str() ) ) cout << "could not find dir " << dir << endl; GetCurrentDirectory( 256, buffer); dir = buffer; } // start recursive directory walk walk(dir); } // //----< walk directory tree rooted at dir >-------------------- void navig::walk(const string &dir) { string fileMask = "*.*"; char *fileName; char curDir[ 256 ]; char fullName[ 256 ]; HANDLE fileHandle; WIN32_FIND_DATA findData; // save current dir so can restore it if( !GetCurrentDirectory( 256, curDir) ) return; // if the directory name is neither . or .. then // change to it, otherwise ignore it if( (dir != "." ) && (dir != ".." ) ) { if( !SetCurrentDirectory( dir.c_str() ) ) return; } else return; // print out the current directory name if( !GetFullPathName( fileMask.c_str(), 256, fullName, &fileName ) ) return; else { GetCurrentDirectory(256,fullName); dp.dirsProc(fullName); } // Loop through all files in the directory fileHandle = FindFirstFile( fileMask.c_str(), &findData ); while ( fileHandle != INVALID_HANDLE_VALUE ) { // If the name is a directory, // recursively walk it. Otherwise print // print the file's data if( findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) walk( findData.cFileName ); else { // configure the fileInfo object with current // data and send to fileProc for processing fi.data = findData; fi._handle = fileHandle; dp.fileProc(fi); } // loop thru remaining entries in the dir if (!FindNextFile( fileHandle, &findData )) break; } // clean up and restore directory FindClose( fileHandle ); SetCurrentDirectory( curDir ); dp.dirsProc(curDir); } // //----< test stub >-------------------------------------------- // // - Recursively walk directory subtree pointed to // by the last command line argument. // - use default navig processing each time a directory // or file is encountered // - replace default processing with user defined processing // and repeat // #ifdef TEST_NAV void main(int argc, char *argv[]) { cout << "\n Testing Directory Navigator " << "\n =============================\n"; if(argc == 1) { cout << "\n please enter starting path\n"; return; } // create default processing object and start navigation cout << "\n testing default dir/file processing: " << "\n --------------------------------------\n"; defProc dp; navig nav(dp); nav.start(argv[argc-1]); cout << "\n\n"; // User defined processing definded here. Note that // local classes can be defined as long as all members // are inline. Otherwise, just declare and define above // main. // // These do nothing but prepend each output with some // "-" characters to show that user defined processing // is actually being used. In a real application user // defined processing will certainly be quite different // from the default class userProc : public defProc { public: virtual void fileProc(const fileInfo &fi) { cout << " --- "; fi.showData(cout); } virtual void dirsProc(const string &dir) { cout << "\n --- " << dir.c_str() << endl; } }; // // restart with user defined processing cout << "\n testing modified dir/file processing: " << "\n ---------------------------------------\n"; userProc udp; navig newNav(udp); newNav.start(argv[argc-1]); cout << "\n\n"; } #endif