如何在删除或复制文件夹树时处理符号链接和连接

时间:2013-12-15 12:28:56

标签: c++ c winapi

我有任务使用win32 api(C ++)复制和删除一个巨大的文件夹,我使用Code Guru recurisive目录删除代码,这很好用,但是出现了一些问题。

RemoveDirectory

  

百万感谢Lerooooy Jenkins指出它。

     

CodeGuru的递归删除链接无法正确处理   符号链接/交叉点。鉴于重新分析点可以指出   在任何地方(甚至是网络驱动器),删除时都需要小心   递归地只删除符号链接/结点而不是它   指向。处理这种情况的正确方法是检测   重新分析点(通过GetFileAttributes())并且不将其作为一个遍历   子目录。

所以我的问题是如何在删除或复制文件夹树时实际处理符号链接和连接。

对于摇摆问题,这里是CodeGuru目录删除的源代码

#include <string>
#include <iostream>

#include <windows.h>
#include <conio.h>


int DeleteDirectory(const std::string &refcstrRootDirectory,
                    bool              bDeleteSubdirectories = true)
{
  bool            bSubdirectory = false;       // Flag, indicating whether
                                               // subdirectories have been found
  HANDLE          hFile;                       // Handle to directory
  std::string     strFilePath;                 // Filepath
  std::string     strPattern;                  // Pattern
  WIN32_FIND_DATA FileInformation;             // File information


  strPattern = refcstrRootDirectory + "\\*.*";
  hFile = ::FindFirstFile(strPattern.c_str(), &FileInformation);
  if(hFile != INVALID_HANDLE_VALUE)
  {
    do
    {
      if(FileInformation.cFileName[0] != '.')
      {
        strFilePath.erase();
        strFilePath = refcstrRootDirectory + "\\" + FileInformation.cFileName;

        if(FileInformation.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
        {
          if(bDeleteSubdirectories)
          {
            // Delete subdirectory
            int iRC = DeleteDirectory(strFilePath, bDeleteSubdirectories);
            if(iRC)
              return iRC;
          }
          else
            bSubdirectory = true;
        }
        else
        {
          // Set file attributes
          if(::SetFileAttributes(strFilePath.c_str(),
                                 FILE_ATTRIBUTE_NORMAL) == FALSE)
            return ::GetLastError();

          // Delete file
          if(::DeleteFile(strFilePath.c_str()) == FALSE)
            return ::GetLastError();
        }
      }
    } while(::FindNextFile(hFile, &FileInformation) == TRUE);

    // Close handle
    ::FindClose(hFile);

    DWORD dwError = ::GetLastError();
    if(dwError != ERROR_NO_MORE_FILES)
      return dwError;
    else
    {
      if(!bSubdirectory)
      {
        // Set directory attributes
        if(::SetFileAttributes(refcstrRootDirectory.c_str(),
                               FILE_ATTRIBUTE_NORMAL) == FALSE)
          return ::GetLastError();

        // Delete directory
        if(::RemoveDirectory(refcstrRootDirectory.c_str()) == FALSE)
          return ::GetLastError();
      }
    }
  }

  return 0;
}


int main()
{
  int         iRC                  = 0;
  std::string strDirectoryToDelete = "c:\\mydir";


  // Delete 'c:\mydir' without deleting the subdirectories
  iRC = DeleteDirectory(strDirectoryToDelete, false);
  if(iRC)
  {
    std::cout << "Error " << iRC << std::endl;
    return -1;
  }

  // Delete 'c:\mydir' and its subdirectories
  iRC = DeleteDirectory(strDirectoryToDelete);
  if(iRC)
  {
    std::cout << "Error " << iRC << std::endl;
    return -1;
  }

  // Wait for keystroke
  _getch();

  return 0;
}

2 个答案:

答案 0 :(得分:3)

使用DeleteFile删除文件符号链接。

使用RemoveDirectory删除目录符号链接和联结。

换句话说,除了没有递归到具有FILE_ATTRIBUTE_REPARSE_POINT属性的目录外,你就像对待任何其他文件或目录一样对待它们。

答案 1 :(得分:1)

实现目标的最简单方法和建议的方法是让系统完成工作。

这些API为您处理所有细节,并使用与shell相同的代码路径。如果需要,您甚至可以显示标准shell进度UI。