简体   繁体   English

c++17 filesystem::remove_all 带通配符路径

[英]c++17 filesystem::remove_all with wildcard path

I want to delete all files, folders and subfolders but not the parent folder.我想删除所有文件、文件夹和子文件夹,但不删除父文件夹。

So I tried to use filesystem::remove_all with a wildcard, but this doesn't seems to work.所以我尝试将 filesystem::remove_all 与通配符一起使用,但这似乎不起作用。

filesystem::removeall("pathtofolder/*");

There is no exception, but it doesn't delete anything.没有例外,但它不会删除任何内容。

Are wildcards are not allowed?是否不允许使用通配符?

Do I really need to call for each file and folder inside of pathtofolder the removeall method?我真的需要为 pathtofolder removeall的每个文件和文件夹调用pathtofolder方法吗?

Are wildcards are not allowed?不允许使用通配符吗?

There is no support for globbing (wildcards) in std::filesystem::remove_all :std::filesystem::remove_all中不支持通配符(通配符):

Deletes the contents of p (if it is a directory) and the contents of all its subdirectories, recursively, then deletes p itself as if by repeatedly applying the POSIX remove .递归删除p的内容(如果它是一个目录)及其所有子目录的内容,然后删除p本身,就像通过重复应用 POSIX remove一样。 Symlinks are not followed (symlink is removed, not its target)不遵循符号链接(删除符号链接,而不是其目标)

Do I really need to call for each file and folder inside of pathtofolder the removeall method?我真的需要为 pathtofolder 中的每个文件和文件夹调用 removeall 方法吗?

Yes, your call should therefore be something like this:是的,因此您的电话应该是这样的:

#include <cstdint>
#include <exception>
#include <filesystem>
#include <iostream>
#include <system_error>

int main() {
    try {
        std::uintmax_t count = 0;

        // loop over all the "directory_entry"'s in "pathtofolder":
        for(auto& de : std::filesystem::directory_iterator("pathtofolder")) {
            // returns the number of deleted entities since c++17:
            count += std::filesystem::remove_all(de.path());
        }
        std::cout << "deleted " << count << " files and directories\n";

    } catch(const std::exception& ex) {
        // The overloads that does not take a std::error_code& parameter throws
        // filesystem_error on underlying OS API errors, constructed with p as
        // the first path argument and the OS error code as the error code
        // argument.

        // directory_iterator:  throws if the directory doesn't exist
        // remove_all:          does NOT throw if the path doesn't exist

        std::cerr << ex.what() << std::endl;
    }
}

Note that if de.path() doesn't exist, it's not an OS API error and it will not throw an exception.请注意,如果de.path()不存在,则不是OS API 错误,也不会throw异常。 It will return 0 deleted files and directories (or false prior to C++17).它将返回0个已删除的文件和目录(或在 C++17 之前为false )。

However, directory_iterator() will throw a filesystem_error if pathtofolder doesn't exist.但是,如果pathtofolder不存在, directory_iterator()将抛出filesystem_error

@TedLyngmo offers a valid solution; @TedLyngmo 提供了一个有效的解决方案; I typically add these things into a utility header, eg in my src/util/filesystem.hpp I put:我通常将这些东西添加到实用程序 header 中,例如在我的src/util/filesystem.hpp中,我输入:

namespace util {
namespace filesystem {

std::uintmax_t remove_all_inside(const std::filesystem::path& dir) {
    std::uintmax_t removed_items_count { 0 };

    if (not is_directory(dir)) { 
        throw std::invalid_argument("Not a directory: " + dir.str());
    }
    for(auto& dir_element : std::filesystem::directory_iterator(dir)) {
        removed_items_count += std::filesystem::remove_all(dir_element .path());
    }
    return removed_items_count;
}

} // namespace filesystem
} // namespace util

and then I can write:然后我可以写:

#include <util/filesystem.hpp>

// ... etc etc ...

util::filesystem::remove_all_inside("/path/to/folder");

A nice aspect of this approach is that it can work with earlier versions of the standard - you just use some preprocessor magic to choose either std::filesystem or boost::filesystem based on the C++ version;这种方法的一个很好的方面是它可以与标准的早期版本一起使用——您只需使用一些预处理器魔法来选择基于 C++ 版本的std::filesystemboost::filesystem but the code using the utility function stays the same.但使用实用程序 function 的代码保持不变。

Example:例子:

std::wregex regExpName { LR"(^.*\.tmp$)" };
const auto tmpPath { std::filesystem::temp_directory_path() };
for (const auto& element : std::filesystem::directory_iterator(tmpPath))
    if (not element.is_directory() and std::regex_match(element.path().filename().wstring(), regExpName))
        std::filesystem::remove(element.path());

I think wildcards are not allowed,我认为不允许使用通配符,

from the documentation it seems that std::filesystem::remove/remove_all map to unlink/rmdir on POSIX systems and DeleteFileW/RemoveDirectoryW on Windows.文档看来,std::filesystem::remove/remove_all map 到 POSIX 系统上的 unlink/rmdir 和 Windows 上的 DeleteFileW/RemoveDirectoryW。

Both don't accept wildcards.两者都不接受通配符。

See: How to remove multiple files in C using wildcards?请参阅: 如何使用通配符删除 C 中的多个文件?

How to use DeleteFile with wildcard in c++ 如何在 c++ 中使用带通配符的 DeleteFile

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM