Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QDir::removeRecursively() fails even on empty folder
Forum Updated to NodeBB v4.3 + New Features

QDir::removeRecursively() fails even on empty folder

Scheduled Pinned Locked Moved Solved General and Desktop
3 Posts 2 Posters 4.7k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • frank.quebecF Offline
    frank.quebecF Offline
    frank.quebec
    wrote on last edited by frank.quebec
    #1

    Greetings,

    I am on Qt 5.4 built with MSVC 2012 (11.0)
    Our app creates temp directories with files in it.
    I am writing the cleanup function.
    qDir->removeRecursively() fails all the time.
    I tried running app as administrator on Windows 7.
    I tried erasing all files in the directory and closing all explorers accessing the folder : still returns false.
    What is wrong with removeRecursively() ?
    Is there a GetLastError() thing to get more info?
    BTW the temp dirs were created inside the temp folder obtained with QDir::tempPath();, for example: C:/Users/Frank/AppData/Local/Temp/GreatAppName_sectionXYZ/checksum_a4fe13430f4a23679eca887664f9d565/
    In this code it would try to clean the folder "checksum_a4fe13430f4a23679eca887664f9d565"

    QDir filenameQDir(dirName);
    QFileInfoList multipleVersionsList = filenameQDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Time);
    
    // The first two ones are the most recent, keep them
    if (multipleVersionsList.size() > 2)
    {
    	for(int i=2; i<multipleVersionsList.size(); i++)
    	{
    		qDebug() << "   " << multipleVersionsList.at(i).absoluteFilePath() << multipleVersionsList.at(i).lastModified();
    		QDir cleanupDir(multipleVersionsList.at(i).absoluteFilePath());
    		if (cleanupDir.removeRecursively())
    		{
    			qDebug() << "Cleaned up old app folder:" << multipleVersionsList.at(i).absoluteFilePath();
    		}
    		else
    		{
    			qDebug() << "ERROR: Failed to cleanup old app folder:" << multipleVersionsList.at(i).absoluteFilePath();
    		}
    	}
    }
    
    1 Reply Last reply
    0
    • mrjjM Offline
      mrjjM Offline
      mrjj
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi and welcome
      I tried on win 10, Qt 5.6
      it did delete it all.
      it was not temp folder, though.

      1 Reply Last reply
      0
      • frank.quebecF Offline
        frank.quebecF Offline
        frank.quebec
        wrote on last edited by frank.quebec
        #3

        I found out what the problem was !
        Files and folders had "read-only" attribute.
        I had to remove attribute on both files and folder before being able to programmatically erase the directory recursively. I first wrote a RemoveDirRecursive() that is more powerful than the Qt's version since it removes read-only attributes. Then I simplified by just writing a RemoveReadOnlyAttributeRecursive() function. Calling this before QDir::removeRecursively() is what I will use as solution. I am attaching the function I wrote as reference. I am going to try on OSX to see if similar behavior is needed:

        /* Usage :
        QString directoryToRemove = "c:/my/super/awesome/directory";
        RemoveReadOnlyAttributeRecursive(directoryToRemove)
        QDir qDir(directoryToRemove);
        qDir.removeRecursively();
        */
        static bool RemoveReadOnlyAttributeRecursive(const QString& directory)
        {
           int failures = 0;
           QDirIterator it(directory, QDirIterator::NoIteratorFlags);
           while (it.hasNext())
           {
              QString fileName = it.next();
              if (fileName.endsWith("/.") || fileName.endsWith("/.."))
                  continue;
        
              QFileInfo fileInfo(fileName);
              if (fileInfo.isDir())
              {
                 if (!RemoveReadOnlyAttributeRecursive(fileName))
                 {
                    qDebug() << "ERROR: Failed to RemoveReadOnlyAttributeRecursive() " << fileName;
                    failures++;
                 }
              }
              else
              {
        #ifdef Q_OS_WIN
                 wchar_t* fileNamePtr = (wchar_t*)fileName.utf16();
                 if (!SetFileAttributes(fileNamePtr, GetFileAttributes(fileNamePtr) & ~FILE_ATTRIBUTE_READONLY))
                 {
                    failures++;
                 }
        #endif
              }
           }
        
        #ifdef Q_OS_WIN
           wchar_t* directoryPtr = (wchar_t*)directory.utf16();
           if (!SetFileAttributes(directoryPtr, GetFileAttributes(directoryPtr) & ~FILE_ATTRIBUTE_READONLY))
           {
              failures++;
           }
        #endif
        
           return failures == 0 ? true : false;
        }
        

        .
        And the one I wrote first but will end up not using:

        static bool RemoveDirRecursive(const QString& directory)
        {
            int failures = 0;
            QDirIterator it(directory, QDirIterator::NoIteratorFlags);
            while (it.hasNext())
            {
                QString fileName = it.next();
                if (fileName.endsWith("/.") || fileName.endsWith("/.."))
                    continue;
        
                QFileInfo fileInfo(fileName);
                if (fileInfo.isDir())
                {
                    if (!RemoveDirRecursive(fileName))
                    {
                        qDebug() << "ERROR: Failed to RemoveDirRecursive() " << fileName;
                        failures++;
                    }
                }
                else
                {
                    if (!QFile::remove(fileName))
                    {
                        qDebug() << "ERROR: Failed to QFile::remove() " << fileName;
        #ifdef Q_OS_WIN
                        wchar_t* fileNamePtr = (wchar_t*)fileName.utf16();
                        SetFileAttributes(fileNamePtr, GetFileAttributes(fileNamePtr) & ~FILE_ATTRIBUTE_READONLY);
                        if (!::DeleteFile(fileNamePtr))
                        {
                            DWORD lastError = ::GetLastError();
                            qDebug() << "ERROR: GetLastError: " << lastError;
                            failures++;
                        }
                        else
                        {
                            qDebug() << "Success on second try with windows API " << fileName;
                        }
        #else
                        failures++;
        #endif
                    }
                }
            }
        
            QDir qDir;
            if(!qDir.remove(directory))
            {
                qDebug() << "ERROR: Failed to qDir.remove() " << directory;
        #ifdef Q_OS_WIN
                wchar_t* directoryPtr = (wchar_t*)directory.utf16();
                SetFileAttributes(directoryPtr, GetFileAttributes(directoryPtr) & ~FILE_ATTRIBUTE_READONLY);
                if (!::RemoveDirectory(directoryPtr))
                {
                   DWORD lastError = ::GetLastError();
                   qDebug() << "ERROR: GetLastError: " << lastError;
                   failures++;
                }
                else
                {
                   qDebug() << "Success on second try delete folder with windows API " << directory;
                }
        #else
                failures++;
        #endif
            }
            else
            {
                qDebug() << "Success qDir.remove " << directory;
            }
        
            return failures == 0 ? true : false;
        }
        
        1 Reply Last reply
        1

        • Login

        • Login or register to search.
        • First post
          Last post
        0
        • Categories
        • Recent
        • Tags
        • Popular
        • Users
        • Groups
        • Search
        • Get Qt Extensions
        • Unsolved