简体   繁体   English

C++ 如何使用 _rmdir 删除文件?

[英]C++ How do I delete files with _rmdir?

I made a simple program that deletes files, however, I don't know how to delete a directory.我做了一个删除文件的简单程序,但是,我不知道如何删除目录。 I saw a few posts saying I need to list all of the files in that directory, delete those files, and then delete the directory/folder itself.我看到一些帖子说我需要列出该目录中的所有文件,删除这些文件,然后删除目录/文件夹本身。 However, somebody suggested using _rmdir which as far as I understand, deletes a directory without any problems, however, it doesn't.但是,有人建议使用 _rmdir ,据我所知,它可以毫无问题地删除目录,但事实并非如此。 Do I still need to list all of the files in a directory in order to delete it with _rmdir?我是否仍然需要列出目录中的所有文件才能使用 _rmdir 删除它? Thanks!谢谢!

Code:代码:

#include <iostream>
#include <string>
#include <sys/stat.h>
#include <Windows.h>
#include <direct.h>
using namespace std;

HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);

inline bool fileExists(const string& filepath) {
    struct stat buffer;
    return (stat(filepath.c_str(), &buffer) == 0);
}

int main()
{
    string filePath;
    string fileAttribute;

    cout << "[~] Enter a path to delete: ";
    getline(cin, filePath);
    cout << "\n[#] Checking if path exists..";
    if (fileExists(filePath) == 1)
    {
        if (GetFileAttributes(filePath.c_str()) == FILE_ATTRIBUTE_DIRECTORY)
        {
            cout << "\n[!] Directory found!";
            _rmdir(filePath.c_str());
            cout << "\n[#] Deleting directory..";
        }
        else
        {
            cout << "\n[!] File found!";
            remove(filePath.c_str());
            cout << "\n[#] Deleting file..";
        }

        if (fileExists(filePath) == 0) 
        {
            SetConsoleTextAttribute(h, 10);
            cout << "\n[!] Deletetion successful!";
            SetConsoleTextAttribute(h, 15);
        }
        else
        {
            SetConsoleTextAttribute(h, 12);
            cout << "\n[!] Deletion unsuccessful!";
            SetConsoleTextAttribute(h, 15);
        }
    }
}   

You probably want the C++17 function std::filesystem::remove_all which deletes the contents of the directory and the contents of all its subdirectories, recursively, then deletes the directory itself as if by repeatedly applying the POSIX remove.您可能需要 C++17 函数std::filesystem::remove_all递归地删除目录及其所有子目录的内容,然后删除目录本身,就像通过重复应用 POSIX 删除一样。 Symlinks are not followed (symlink is removed, not its target).不遵循符号链接(删除符号链接,而不是其目标)。


Edit: As Eryk Sun pointed out in the comments, it's good to test that the recursive removal does not follow Windows junctions, which would lead to unwanted removal of everything the junction points at.编辑:正如 Eryk Sun 在评论中指出的那样,最好测试递归删除不遵循 Windows 连接点,这会导致不必要地删除连接点指向的所有内容。

I made a test that used std::filesystem::create_directory_symlink to create a symlink and then use the WinAPI to check if that symlink became a junction, which it reportedly did - a junction has the FILE_ATTRIBUTE_REPARSE_POINT attribute and the reparse point tag IO_REPARSE_TAG_MOUNT_POINT .我做了一个测试,使用std::filesystem::create_directory_symlink创建一个符号链接,然后使用 WinAPI 来检查该符号链接是否成为一个连接点,据报道它确实做到了 - 一个连接点具有FILE_ATTRIBUTE_REPARSE_POINT属性和重新解析点标记IO_REPARSE_TAG_MOUNT_POINT Interestingly it also had the IO_REPARSE_TAG_SYMLINK tag.有趣的是它还有IO_REPARSE_TAG_SYMLINK标签。 When using normal DOS commands I noticed that the link was indeed reported as a plain <SYMLINKD> and not a <JUNCTION> .当使用普通的DOS命令时,我注意到链接确实被报告为一个普通的<SYMLINKD>而不是一个<JUNCTION>

I then used MKLINK /J to create a junction.然后我使用MKLINK /J创建一个连接。 That junction was indeed reported as a <JUNCTION> by DOS and running std::filesystem::remove_all() on it removed it, but not what it pointed at.该连接确实被DOS报告为<JUNCTION>并在其上运行std::filesystem::remove_all()删除了它,但不是它所指向的。

I also downloaded the sysinternals Junction utility and used that to create a junction.我还下载了 sysinternals Junction实用程序并使用它来创建一个连接。

That junction was also reported as a <JUNCTION> by DOS , but running std::filesystem::remove_all() on it had another effect.该结点也被DOS报告为<JUNCTION> ,但在其上运行std::filesystem::remove_all()有另一个效果。 It did not remove it (or what it pointed at).没有将其删除(或它指向)。

So remove_all() should be safe with regards to junctions - but perhaps even too safe.因此remove_all()应该是安全的,但可能安全了。 I didn't try to find out what the difference was between the MKLINK junction and the junction created by the sysinternals utility.我没有试图找出MKLINK连接和由 sysinternals 实用程序创建的连接之间的MKLINK

Do I still need to list all of the files in a directory in order to delete it with _rmdir?我是否仍然需要列出目录中的所有文件才能使用 _rmdir 删除它?

Why don't you simply read the documentation ?你为什么不简单地阅读文档

It says:它说:

The _rmdir function deletes the directory specified by dirname. _rmdir 函数删除由 dirname 指定的目录。 The directory must be empty , and it must not be the current working directory or the root directory.该目录必须为空,并且不能是当前工作目录或根目录。

That's pretty much the case for any "remove directory" functionality.任何“删除目录”功能几乎都是这种情况。 It's what your Windows Explorer UI is doing behind the scenes when you hit delete on your keyboard.当您按键盘上的删除键时,这就是您的 Windows 资源管理器 UI 在幕后所做的事情。

This is also the case for std::filesystem::remove , but std::filesystem::remove_all will do all that recursion for you.这也是std::filesystem::remove ,但std::filesystem::remove_all将为您完成所有递归。

您可以使用:

std::filesystem::remove_all("path/myDirectory");

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

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