Thread: deleting directory structure routine (with code tags this time)

  1. #1
    Registered User
    Join Date
    Jul 2003
    Posts
    10

    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);

    //***
    :eleteFile(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)
    Mullah,
    MSVC++6.0
    (Win 2K Pro)

  2. #2
    Registered User
    Join Date
    Oct 2002
    Posts
    291

  3. #3
    *******argv[] - hu? darksaidin's Avatar
    Join Date
    Jul 2003
    Posts
    314
    Originally posted by Salem
    Please use [code][/code]Tags
    Sheesh!!!
    And disable smilies for a code post. Similies in a code maybe funny, but don't really rock

  4. #4
    Registered User
    Join Date
    Jul 2003
    Posts
    10

    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).
    Mullah,
    MSVC++6.0
    (Win 2K Pro)

  5. #5
    End Of Line Hammer's Avatar
    Join Date
    Apr 2002
    Posts
    6,231
    Threads merged
    When all else fails, read the instructions.
    If you're posting code, use code tags: [code] /* insert code here */ [/code]

  6. #6
    Registered User
    Join Date
    Jul 2003
    Posts
    10
    Thank you, but if you call RemoveDirRecurse there you get an access violation (you can't call a recursive function twice because it overwrites it's block memory stack the second time you call it).
    Look at the block where I have my RemoveDirRecurse recursive call
    Code:
    if (pDW->fRecurse)
    {
         .....
         RemoveDirRecurse(pDW);
    }
    And now look at the code:
    Code:
    else if (pDW->fIsDir && pDW->fRecurse)
    	{
    		if (pDW->FindData.cFileName == _T(""))
    		{
    			::RemoveDirectory((const char*) pDW->FindData.cFileName);
    		}
    	}
    The question is: how do you test that a subdir is empty? We're not dealing with CStrings here so that you can test it with IsEmpty().
    So, I tried with if (pDW->FindData.cFileName == _T(""))
    It still doesn't delete all the subdirs.
    Mullah,
    MSVC++6.0
    (Win 2K Pro)

  7. #7
    Registered User
    Join Date
    Jul 2003
    Posts
    10
    Ok sir, thank you.
    Mullah,
    MSVC++6.0
    (Win 2K Pro)

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Obfuscated Code Contest
    By Stack Overflow in forum Contests Board
    Replies: 51
    Last Post: 01-21-2005, 04:17 PM
  2. Request for comments
    By Prelude in forum A Brief History of Cprogramming.com
    Replies: 15
    Last Post: 01-02-2004, 10:33 AM
  3. Serial Communications in C
    By ExDigit in forum Windows Programming
    Replies: 7
    Last Post: 01-09-2002, 10:52 AM
  4. Use Code Tags!
    By Govtcheez in forum C++ Programming
    Replies: 9
    Last Post: 09-06-2001, 12:57 PM
  5. Use Code Tags!
    By Govtcheez in forum C Programming
    Replies: 7
    Last Post: 09-04-2001, 06:54 PM