Nominate our 2022 Qt Champions!

QDir delete all files function?

  • Hi-

    I'm wondering if anyone else would find it useful to have a function in QDir (maybe static) that would remove all the files in the directory? This seems like a pretty common thing to do. If so, where does one go to post feature requests? Not sure if this has ever been disucssed before, nothing seemed to come up when I searched...

    Seems fairly easy to implement, but it would still be nice to be wrapped in a function.

  • Oh, and maybe also recursively delete all subdirs, stuff like that.

  • If you want to file a suggestion, you can do on "JIRA":

  • It's doesn't make sense because you can't catch errors in this process,
    for example what do this method doing if one of file is blocked of OS?
    When you realize this function self, you can make needed handling for exception cases.

  • well a base implementation with skipping undeletable files would make sense. f.e. you write your own installer / uninstaller and want to delete a folder that was shipped with your application. you can be pretty much sure that no one else is using this files.

  • Nazgul, This is a very particular task, especially, considering that recursive pass are very simple issue.

  • [quote author="Nazgul" date="1316505197"]you can be pretty much sure that no one else is using this files.[/quote]

    You can never make any assumption on if and who is using your files!

    The virus protection, an indexing service, a loaded shared library, an open command promt, the thumbnailer or icon cache refreshing - there are tons of possibilities which might and will use your files without any notice and will prevent you from deleting them.

  • i said its unlikely that they are used. they can be used thats true. but in this case, skipping the file is an option in a default implementation.

  • Ok, Simple question, QDir::remove method return true if file removed and false if not.

    What will return your QDir::removeAll method when only some files (not all) was removed.

  • it returns an int, 0 if all files deleted and else the number of remaining files

  • [quote author="Nazgul" date="1316509755"]and else the number of remaining files[/quote]
    or number of remaining files and folders
    or pointer to hash or list of remaining files and folders? :)

    I'm not against general removeAll method completely,
    Just I think it must be very smart method,
    with signals or with callback for catching problems.
    But for small tasks this smart method can seems very difficult way.

  • perhaps you can have a enum parameter, like in the dirfilters, to choose the behavior of the method.

    f.e. IgnoreAll, CountFiles, CountFilesAndFolders

    and perhaps as an out parameter a QList<QFileInfo> for the files that remained (default empty list)

  • The number of remaining files represents the same amount of information as a boolean value which indicates if there are any remaining files.

    Yes, there might be situations where a convenient QDir::removeAll() method makes sense. But in most of the situations you will end up in writing code around this method which handles situations where it couldn't remove all.

    One of the principles in API design (and probably the one most violated) is to not cover every use case just for convenience, especially if this use case does not fully represent real-life situations encountered - this keeps the API clean and simple. This might be the reason there is no such method in the Qt API in the first place (which does not mean that such a method wouldn't make sense in some situations).

  • Wow... quite a discussion around what I thought was a fairly simple matter. I'm just looking for a function that I use in boost frequently.

  • [quote author="medvedm" date="1316524223"]Wow... quite a discussion around what I thought was a fairly simple matter. I'm just looking for a function that I use in boost frequently.

    You can still use it, you know. Qt and Boost can play nicely together.

  • Further problems can arise with a general DeleteAll. We implemented a method like this, but I can see why it cannot be generalized enough. (Our implementation is purely for cleanup purposes, so it will return false right after the first remove fails or can be specified to skip the failed files if not that important)

    Problem 1: what type of files?
    We ended with a list-files like this one:
    @QFileInfoList files = topDir.entryInfoList(QDir::NoDotAndDotDot | QDir::Files | QDir::Hidden | QDir::System/* | QDir::NoSymLinks*/);@

    The symlinks have to be handled with special care - one of our implementation resolved the symlink files and tried to remove the target - which is in some cases a system directory (like Documents or Music in Windows) or file (like the shutdown.exe)! But in other projects resolving symlinks can be a criteria.

    So after we removed the files in the given directory we list the sub-directories like this:
    @QFileInfoList dirs = topDir.entryInfoList(QDir::NoDotAndDotDot | QDir::Dirs | QDir::Hidden | QDir::System);@

    We can remove the System directories because we know it won't be used in directories like "Program Files" or "Windows" (in Windows OSs of course), but it's also cannot be used as a general method because with less care it can make trouble.

    And the symlinks to directories have to be handled differently to not to resolve the link, only remove the symlink files to directory (not the target directory)

    And of course it's a recursive method which removes the given directory after it removed every files and sub-directories under.

    I hope it can demonstrate that there's a lot of use cases and I don't think a general implementation could used in every case. Maybe a delegate or signal/slot based implementation, but I think it's safer to implement your own and give it a proper name indicates where it can be used.

    Also our implementation is about 60 lines with conditional debug-logging as well, so it's not that hard to write one, and this way you can ensure (and you have to ensure!) the right usage.

  • I was about to implement it in Qt when I read this discussion... Very interesting.

    My first instinct was to reply this:

    "I would have stopped on the first error (like KIO does) and returned a bool. But a flag to ignore errors and keep going could indeed be interesting, e.g. for the case of temporary directories, where we just want to clean up as much as possible. This is also what rm -rf appears to do.

    I don't see what's "non general" about this. True, it won't do the job for a file manager (who should report more details on errors and provide the user with options), but it will do for many cases of programmatically deleting a dir, like temp dirs."

    Temp dirs. But indeed not install dirs (these are more like a file manager operation which should tell the user what couldn't be deleted).

    I admit that the use case I have in mind is really temp dirs (I want to add QTemporaryDir to Qt), but putting the remove-recursive code inside the temp-dir class felt wrong, this is why I was looking at putting it in QDir.

    However I just looked all over KDE (as an example of a huge code base of libs and apps), and the only non-user-oriented task for removing directories are:

    • safe (random-named) temp dirs
    • fixed-named temp dirs as used by unittests for easier debugging.
    • konqueror sessions which are saved on disk as dirs.

    Everything else is user-oriented, which means that it should support

    • proper error reporting (telling the user which files couldn't be removed)
    • proper progress reporting and even ideally an async job (you don't want to block the application for 10 minutes while deleting a huge dir with huge files)
    • network transparency, if possible (which is the case in KDE).
      All of this disqualifies a QDir::removeAll method.
      In fact, having one at that level would mislead people into using it for user-oriented operations, which would not be good.

    Instead I'm now thinking that it should be a static method of the QTemporaryDir class which I'm about to write, so that people can call it on temporary dirs, whether they were created with a random name by the class, or with a fixed name [in unittests]. Technically it means people can still call it in all use cases, but the naming makes it clear that it is meant for small local hidden-from-the-user temp dirs, not for generic user-visible directories.

    This is the way it has been in KDE for many years, and I see that it hasn't been abused :-)


  • Sounds like a plan to me.

  • After more discussions on the qt5 development list, and in the code review tool, it's finally done.

    Qt5 now has QDir::removeRecursively().

  • Moderators

    Nice, thanks!

Log in to reply