Dateien zählen und ältere löschen



  • Hallo liebe Leute,

    ich arbeite an einem Programm das beim Beenden Sicherungsdateien der letzten Konfiguration mit einem Zeitstempel im Namen erstellt. Das Programm läuft unter Ubuntu.

    Es soll jetzt eine maximale Anzahl an Dateien erstellt werden und die ältesten sollen gelöscht werden.

    Die Dateien heißen alle "autosave-YYYY:MM:DD-HH:MM:SS.cfg"

    Wie zähle ich die Dateien, die mit "autosave..." beginnen und lösche sie dann?

    Vielen Dank für jede Hilfe.



  • Welche Programmiersprache?



  • Hab es geschafft. War verdammt mühselig. Wer sowas braucht kanns verwenden. 🙂

    Sprache ist gnu c++ version 4.3.

    #include <dirent.h>
      #include <algorithm>
      ...
    
      DIR *hdir;
      struct dirent *entry;
      std::string str;
      vector<string> myvector;
      unsigned int size = 0;
    
      //ordner öffnen und dateien auslesen
      hdir = opendir("media");
      do{
        entry = readdir(hdir);
        if (entry){
          str = entry->d_name;
          if (str.find("autosave") != string::npos )
            myvector.push_back(str);
        }
    
      }while(entry);
    
      //dateien zählen
      if (myvector.size() > 1000){
    
        //wenn zu viele sortieren
        sort(myvector.begin(), myvector.end());
    
        char path[50];
        sprintf(path, "./media/%s", myvector[0].c_str());
    
        //und älteste löschen
        if (remove(path) == 0){
          cout << "REMOVE ERFOLGREICH" << endl;
        }
        else{
          cout << "KONNTE DATEI NICHT LÖSCHEN" << endl;
        }
      }
    


  • uh sprintf? Mit festem String? Da muss nur jemand eine Datei mit einem Namen länger als 50 Zeichen anlegen der irgend wo "autosave" enthält und schon stürzt dein Programm ab oder kann gar exploitet werden.

    Hier mal ein paar kleine Verbesserungen

    #include <dirent.h>
      #include <algorithm>
      ...
    
      vector<string> savefiles;
    
      //Verzeichnis öffnen und Dateien auslesen
      DIR *hdir = opendir("media");
      if(!hdir) {
        perror("opendir");
        return -1;
      }
      dirent *entry;
      while( (entry = readdir(hdir)) ) {
        string str = entry->d_name;
        if(str.compare(0, 8, "autosave", 8) == 0)
          savefiles.push_back(str);
      }
      closedir(hdir);
    
      //dateien zählen
      if (savefiles.size() > 1000){
    
        //wenn zu viele sortieren
        sort(savefiles.begin(), savefiles.end());
    
        string path = string("./media/") + myvector[0];
    
        //und älteste löschen
        if (remove(path.c_str()) == 0){
          cout << "REMOVE ERFOLGREICH" << endl;
        }
        else{
          cout << "KONNTE DATEI NICHT LÖSCHEN" << endl;
        }
      }
    

    Wobei das ganze in Shellscript ein paar Zeilen wären. Irgend wie in die Richtung

    #!/bin/bash
    
    MAXFILES=1000
    NOOFFILES=`ls -l autosave-* | wc -l`
    echo "$NOOFFILES Files"
    if [ "$NOOFFILES" -gt "$MAXFILES" ]; then
        echo "Cleaning $(($NOOFFILES-$MAXFILES)) Files"
        ls -c | tail -n $(($NOOFFILES-$MAXFILES)) | xargs echo # hier rm - anstelle von echo. 
    fi
    


  • Geil, danke alter! 😃
    Ich lasse meinen Code immer gerne professionel überarbeiten, so lernt man was!
    Das werd ich morgen noch so optimieren.

    Länger als 50 Zeilen wird das nicht. Wie gesagt, die Dateinamen haben immer ein festes Format das aus "autosave" + Zeitstempel besteht.

    Dankööö



  • Länger als 50 Zeilen wird das nicht. Wie gesagt, die Dateinamen haben immer ein festes Format das aus "autosave" + Zeitstempel besteht.

    Das hat man bei der Ariane 5 auch geglaubt.
    Selbst bei Wegwerfcode sollte man nicht mit dieser Einstellung herangehen. Arrayüberläufe sind gemeingefährlich, da sie das Programmverhalten auch an ganz anderen Stellen verändern können - und bei einem Programm, das mit Dateien hantiert, ist so etwas besonders riskant.
    Und die sichere Variante kostet selten mehr, oft ist das Gegenteil der Fall (wie hier).


Anmelden zum Antworten