wake-up-neo.com

Wie können Sie alle Dateien in einem Ordner löschen, den Ordner jedoch nicht mit NIX-Standardbibliotheken löschen?

Ich versuche, ein Programm zu erstellen, das den Inhalt des/tmp-Ordners löscht. Ich verwende C/C++ unter Linux.

system("exec rm -r /tmp")

löscht alles im Ordner, aber es löscht auch den Ordner, den ich nicht möchte.

Gibt es eine Möglichkeit, dies durch ein bash-Skript zu tun, das über system() aufgerufen wird; oder gibt es eine direkte Möglichkeit, dies in C/C++ zu tun?

Meine Frage ist ähnlich wie diese, aber ich bin nicht auf OS X ... wie lösche ich alle Dateien in einem Ordner, aber nicht den Ordner selbst?

In C/C++ können Sie Folgendes tun:

system("exec rm -r /tmp/*")

In Bash können Sie Folgendes tun:

rm -r /tmp/*

Dadurch wird alles in/tmp gelöscht, nicht jedoch in/tmp.

15
Jay Sullivan
#include <stdio.h>
#include <dirent.h>

int main()
{
    // These are data types defined in the "dirent" header
    DIR *theFolder = opendir("path/of/folder");
    struct dirent *next_file;
    char filepath[256];

    while ( (next_file = readdir(theFolder)) != NULL )
    {
        // build the path for each file in the folder
        sprintf(filepath, "%s/%s", "path/of/folder", next_file->d_name);
        remove(filepath);
    }
    closedir(theFolder);
    return 0;
}

Sie möchten keine neue Shell über system() oder etwas Ähnliches erzeugen - dies ist viel Aufwand, um etwas sehr einfaches zu tun, und macht unnötige Annahmen (und Abhängigkeiten) über das, was im System verfügbar ist.

44
Demitri

mit dem Platzhalterzeichen * können Sie alle Dateien mit einer beliebigen Erweiterung löschen.

system("exec rm -r /tmp/*")

3
eqzx

du kannst tun

system("exec find /tmp -mindepth 1 -exec rm {} ';'");
3
ALiX

In C/C++ können Sie (einschließlich versteckter Verzeichnisse) Folgendes verwenden:

system("rm -r /tmp/* /tmp/.*");
system("find /tmp -mindepth 1 -delete");

Aber was ist, wenn 'rm' oder 'find' Dienstprogramme nicht für sh verfügbar sind?

#define _XOPEN_SOURCE 500
#include <ftw.h>

static int remove_cb(const char *fpath, const struct stat *sb, int typeFlag, struct FTW *ftwbuf)
{
    if (ftwbuf->level)
        remove(fpath);
    return 0;
}

int main(void)
{
    nftw("./dir", remove_cb,  10, FTW_DEPTH);
    return 0;
}
1
cmllamas

Ich weiß, dass dies eine sehr alte Frage ist, aber basierend auf Demitris großartiger Antwort habe ich eine Funktion erstellt, die Dateien in Unterordnern rekursiv löscht, wenn dies gewünscht wird

Es macht auch einige Fehlerbehandlung, indem es errno zurückgibt. Der Funktionsheader wird für die Analyse von doxygen geschrieben. Diese Funktion funktioniert in den einfachen Fallbeispielen, die ich verwendet habe, und löscht verborgene Ordner und versteckte Dateien.

Ich hoffe das hilft in Zukunft jemand anderem

#include <stdio.h>
#include <dirent.h>
#include <sys/stat.h>
#define SUCCESS_STAT 0

/**
 * checks if a specific directory exists
 * @param dir_path the path to check
 * @return if the path exists
 */
bool dirExists(std::string dir_path)
{
    struct stat sb;

    if (stat(dir_path.c_str(), &sb) == 0 && S_ISDIR(sb.st_mode))
        return true;
    else
        return false;
}

/**
 * deletes all the files in a folder (but not the folder itself). optionally
 * this can traverse subfolders and delete all contents when recursive is true
 * @param dirpath the directory to delete the contents of (can be full or
 * relative path)
 * @param recursive true = delete all files/folders in all subfolders
 *                  false = delete only files in toplevel dir
 * @return SUCCESS_STAT on success
 *         errno on failure, values can be from unlink or rmdir
 * @note this does NOT delete the named directory, only its contents
 */
int DeleteFilesInDirectory(std::string dirpath, bool recursive)
{
    if (dirpath.empty())
        return SUCCESS_STAT;

    DIR *theFolder = opendir(dirpath.c_str());
    struct dirent *next_file;
    char filepath[1024];
    int ret_val;

    if (theFolder == NULL)
        return errno;

    while ( (next_file = readdir(theFolder)) != NULL )
    {
        // build the path for each file in the folder
        sprintf(filepath, "%s/%s", dirpath.c_str(), next_file->d_name);

        //we don't want to process the pointer to "this" or "parent" directory
        if ((strcmp(next_file->d_name,"..") == 0) ||
            (strcmp(next_file->d_name,"." ) == 0) )
        {
            continue;
        }

        //dirExists will check if the "filepath" is a directory
        if (dirExists(filepath))
        {
            if (!recursive)
                //if we aren't recursively deleting in subfolders, skip this dir
                 continue;

            ret_val = DeleteFilesInDirectory(filepath, recursive);

            if (ret_val != SUCCESS_STAT)
            {
                closedir(theFolder);
                return ret_val;
            }
        }

        ret_val = remove(filepath);
        //ENOENT occurs when i folder is empty, or is a dangling link, in
        //which case we will say it was a success because the file is gone
        if (ret_val != SUCCESS_STAT && ret_val != ENOENT)
        {
            closedir(theFolder);
            return ret_val;
        }

    }

    closedir(theFolder);

    return SUCCESS_STAT;
}
1
andrew

Sie könnten nftw (3) verwenden. Machen Sie zunächst einen Pass, um die zu entfernenden Dateipfade zu sammeln. Verwenden Sie dann unlink (für Nicht-Verzeichnisse) und rmdir (2) in einem zweiten Durchlauf