deleting a directory structure
Hi!
I'm a VC++ programmer. I need a recursive routine that deletes all the subdirs and files from within a parent(root) directory. This root directory should be taken as a parameter (LPCTSTR or CString) when you call the function.
Here is some code which compiles but doesn't do it's job (deleting):
// This macro evaluates to the number of elements in an array.
#define chDIMOF(Array) (sizeof(Array) / sizeof(Array[0]))
typedef struct
{
int nDepth; // Nesting depth
BOOL fRecurse; // Set to TRUE to list subdirectories
TCHAR szBuf[1000]; // Output formatting buffer
int nIndent; // Indentation character count
BOOL fOk; // Loop control flag
BOOL fIsDir; // Loop control flag
WIN32_FIND_DATA FindData; // File information
} DIRWALKDATA, *LPDIRWALKDATA;
static void RemoveDirRecurse(LPDIRWALKDATA pDW)
{
HANDLE hFind;
pDW->nDepth++;
pDW->nIndent = 3 * pDW->nDepth;
_stprintf(pDW->szBuf, _TEXT("%*s"), pDW->nIndent, _TEXT(""));
GetCurrentDirectory(chDIMOF(pDW->szBuf) - pDW->nIndent, &pDW->szBuf[pDW->nIndent]);
// ***
::RemoveDirectory(pDW->szBuf);
hFind = FindFirstFile(_TEXT("*.*"), &pDW->FindData);
pDW->fOk = (hFind != INVALID_HANDLE_VALUE);
while (pDW->fOk)
{
pDW->fIsDir = pDW->FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
if (!pDW->fIsDir || (!pDW->fRecurse && IsChildDir(&pDW->FindData)))
{
_stprintf(pDW->szBuf,
pDW->fIsDir ? _TEXT("%*s[%s]") : _TEXT("%*s%s"),
pDW->nIndent, _TEXT(""),
pDW->FindData.cFileName);
//***
::DeleteFile(pDW->szBuf);
}
pDW->fOk = FindNextFile(hFind, &pDW->FindData);
}
if (hFind != INVALID_HANDLE_VALUE)
FindClose(hFind);
if (pDW->fRecurse)
{
// Get the first child directory
hFind = FindFirstChildDir(_TEXT("*.*"), &pDW->FindData);
pDW->fOk = (hFind != INVALID_HANDLE_VALUE);
while (pDW->fOk)
{
// Change into the child directory
if (SetCurrentDirectory(pDW->FindData.cFileName))
{
// Perform the recursive walk into the child directory.
// Remember that some members of pDW will be overwritten by this call.
RemoveDirRecurse(pDW);
// Change back to the child's parent directory.
SetCurrentDirectory(_TEXT(".."));
}
pDW->fOk = FindNextChildDir(hFind, &pDW->FindData);
}
if (hFind != INVALID_HANDLE_VALUE)
FindClose(hFind);
}
pDW->nDepth--;
}
void CAfisare::RemoveCurDir(LPCTSTR pszRootPath, BOOL fRecurse)
{
TCHAR szCurrDir[_MAX_DIR];
DIRWALKDATA DW; // Create instance of DIRWALKDATA
// Save the current directory so that it can be restored later.
GetCurrentDirectory(chDIMOF(szCurrDir), szCurrDir);
// Set the current directory to where you want to start walking
SetCurrentDirectory(pszRootPath);
// nDepth is used to control indenting. The value -1 will cause
// the first level to display flush left.
DW.nDepth = -1;
DW.fRecurse = fRecurse;
RemoveDirRecurse(&DW);
// Restore the current directory to what it was before the function was called.
SetCurrentDirectory(szCurrDir);
}
void CAfisare::OnTest()
{
CString strRootPath = "C:\\KE1c_SL";
RemoveCurDir(strRootPath, TRUE);
}
Maybe you have a better idea,
Thanx,
Gord,
MS VC++ 6.0
(Win 2K Pro)
deleting directory structure routine (with code tags this time)
Code:
// This macro evaluates to the number of elements in an array.
#define chDIMOF(Array) (sizeof(Array) / sizeof(Array[0]))
typedef struct
{
int nDepth; // Nesting depth
BOOL fRecurse; // Set to TRUE to list subdirectories
TCHAR szBuf[1000]; // Output formatting buffer
int nIndent; // Indentation character count
BOOL fOk; // Loop control flag
BOOL fIsDir; // Loop control flag
WIN32_FIND_DATA FindData; // File information
} DIRWALKDATA, *LPDIRWALKDATA;
static BOOL IsChildDir (WIN32_FIND_DATA *lpFindData)
{
return(
((lpFindData->dwFileAttributes &
FILE_ATTRIBUTE_DIRECTORY) != 0) &&
(lstrcmp(lpFindData->cFileName, _TEXT(".")) !=0) &&
(lstrcmp(lpFindData->cFileName, _TEXT("..")) != 0));
}
static BOOL FindNextChildDir (HANDLE hFindFile, WIN32_FIND_DATA *lpFindData)
{
BOOL fFound = FALSE;
do
{
fFound = FindNextFile(hFindFile, lpFindData);
} while (fFound && !IsChildDir(lpFindData));
return(fFound);
}
static HANDLE FindFirstChildDir (LPTSTR szPath, WIN32_FIND_DATA *lpFindData)
{
BOOL fFound;
HANDLE hFindFile = FindFirstFile(szPath, lpFindData);
if (hFindFile != INVALID_HANDLE_VALUE)
{
fFound = IsChildDir(lpFindData);
if (!fFound)
fFound = FindNextChildDir(hFindFile, lpFindData);
if (!fFound)
{
FindClose(hFindFile);
hFindFile = INVALID_HANDLE_VALUE;
}
}
return (hFindFile);
}
static void RemoveDirRecurse(LPDIRWALKDATA pDW)
{
HANDLE hFind;
pDW->nDepth++;
pDW->nIndent = 3 * pDW->nDepth;
_stprintf(pDW->szBuf, _TEXT("%*s"), pDW->nIndent, _TEXT(""));
GetCurrentDirectory(chDIMOF(pDW->szBuf) - pDW->nIndent, &pDW->szBuf[pDW->nIndent]);
hFind = FindFirstFile(_TEXT("*.*"), &pDW->FindData);
pDW->fOk = (hFind != INVALID_HANDLE_VALUE);
while (pDW->fOk)
{
pDW->fIsDir = pDW->FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
if (!pDW->fIsDir || (!pDW->fRecurse && IsChildDir(&pDW->FindData)))
{
//*** (API function)
::DeleteFile(pDW->FindData.cFileName);
}
else if (pDW->fIsDir || (IsChildDir(&pDW->FindData) && pDW->fRecurse))
{ //*** (API function)
::RemoveDirectory((const char*) pDW->FindData.cFileName);
}
pDW->fOk = FindNextFile(hFind, &pDW->FindData);
}
if (hFind != INVALID_HANDLE_VALUE)
FindClose(hFind);
if (pDW->fRecurse)
{
// Get the first child directory
hFind = FindFirstChildDir(_TEXT("*.*"), &pDW->FindData);
pDW->fOk = (hFind != INVALID_HANDLE_VALUE);
while (pDW->fOk)
{
// Change into the child directory
if (SetCurrentDirectory(pDW->FindData.cFileName))
{
// Perform the recursive walk into the child directory.
// Remember that some members of pDW will be overwritten by this call.
RemoveDirRecurse(pDW);
// Change back to the child's parent directory.
SetCurrentDirectory(_TEXT(".."));
}
pDW->fOk = FindNextChildDir(hFind, &pDW->FindData);
}
if (hFind != INVALID_HANDLE_VALUE)
FindClose(hFind);
}
pDW->nDepth--;
}
void CAfisare::RemoveCurDir(LPCTSTR pszRootPath, BOOL fRecurse)
{
TCHAR szCurrDir[_MAX_DIR];
DIRWALKDATA DW; // Create instance of DIRWALKDATA
// Save the current directory so that it can be restored later.
GetCurrentDirectory(chDIMOF(szCurrDir), szCurrDir);
// Set the current directory to where you want to start walking
SetCurrentDirectory(pszRootPath);
// nDepth is used to control indenting. The value -1 will cause
// the first level to display flush left.
DW.nDepth = -1;
DW.fRecurse = fRecurse;
RemoveDirRecurse(&DW);
// Restore the current directory to what it was before the function was called.
SetCurrentDirectory(szCurrDir);
}
void CAfisare::OnTest()
{
CString strRootPath = "C:\\KE1c_SL";
RemoveCurDir(strRootPath, TRUE);
}
Well, this time the routine deletes all the files it finds, but not the subdirs (or, not all the subdirs).