简体   繁体   中英

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. Do I still need to list all of the files in a directory in order to delete it with _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. 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.

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 . Interestingly it also had the IO_REPARSE_TAG_SYMLINK tag. When using normal DOS commands I noticed that the link was indeed reported as a plain <SYMLINKD> and not a <JUNCTION> .

I then used MKLINK /J to create a junction. 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.

I also downloaded the sysinternals Junction utility and used that to create a junction.

That junction was also reported as a <JUNCTION> by DOS , but running std::filesystem::remove_all() on it had another effect. 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. I didn't try to find out what the difference was between the MKLINK junction and the junction created by the sysinternals utility.

Do I still need to list all of the files in a directory in order to delete it with _rmdir?

Why don't you simply read the documentation ?

It says:

The _rmdir function deletes the directory specified by 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.

This is also the case for std::filesystem::remove , but std::filesystem::remove_all will do all that recursion for you.

您可以使用:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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