Löschen von älteren Backupdateien
-
@deamonwannabee sagte in Löschen von älteren Backupdateien:
@SeppJ
Ich weiß nicht, wie ich mit Hilfe der Funktion "GetFileAttributes", welche ich meines Wissens dafür brauche,Was meinst du denn, was du davon brauchst?
Wie möchtest du überhaupt vorgehen?
Ist nur der Dateiname interessant oder möchtest du nach dem tatsächlichen Erstell-/Änderungs-/Zugriffszeitpunkt gehen?
-
In bash würde ich ja vorschlagen:
(Edit - SeppJ hat natürlich Recht: nur im konreten Fall der bekannten Dateinamen verwendbar; funktioniert nicht, wenn Dateinamen nicht gutartig sind (Spaces, Zeilenumbrüche, ... im Dateinamen) oder gar keine Datei passt oder Verzeichnisse mit dabei sind)ls -t1 | tail -n +11 | xargs rm
Ansonsten in C++: mach dir einen std::vector von struct { filename, time}, sortiere nach time und lösche alle Daten ab Index 10.
Auflisten: siehe https://en.cppreference.com/w/cpp/filesystem/directory_iterator
Zeit: siehe z.B. https://en.cppreference.com/w/cpp/filesystem/last_write_time
-
Wenn du das mit der WINAPI lösen möchtest:
FindFirstFile
mit entsprechendem Dateipfad und -maske aufrufen ( "c:\data\backups\backup*.*")- absoluten Dateinamen aus Verzeichnisnamen und Treffer aus 1) bilden
CreateFile
mit Dateinamen aus 2) zum Lesen aufrufen- Mit dem
HANDLE
aus 3)GetFileTime()
aufrufen - Zeittempel aus 4) zusammen mit dem Dateinamen aus 2) in eine Datenstruktur packen (struct, pair<>) und in einen
vector
einfügen - mit
FindNextFile
die nächste Datei bestimmen. Falls es eine gibt: weiter bei 2) - Vektor nach Zeitstempel sortieren
- Alle Dateien im Vektor ab Eintrag 10 löschen
Pseudocode:
#include <windows.h> #include <string> #include <vector> #include <algorithm> struct FileEntry { std::string FileName; FILETIME CreationTime = 0; FILETIME LastAccessTime = 0; FILETIME LastWriteTime = 0; }; void remove_backups() { std::string const backup_directory = "c:\\tmp\\backups\\"; std::string const search_pattern = backup_directory + "backup*.*"; std::vector<FileEntry> file_entries; WIN32_FIND_DATA wfd; HANDLE find_handle = FindFirstFile( search_pattern.c_str(), &wfd ); if( find_handle != INVALID_HANDLE_VALUE ) { do { if( !(wfd.wdFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) { FileEntry fe; fe.FileName = backup_directory + wfd.cFileName; HANDLE file_handle = CreateFile( fe.FileName.c_str(), ... ); if( file_handle != INVALID_HANDLE_VALUE ) { if( GetFileTime( file_handle, &fe.CreationTime, &fe.LastAccessTime, &fe.LastWriteTime ) ) { file_entries.push_back( fe ); } CloseHandle( file_handle ); } } } while( FindNextFile( find_handle , &wfd ) ); FindClose( find_handle ); } if( file_entries.size() > 10 ) { std::sort( file_entries.begin(), file_entries.end(), ... ); for( auto i = file_entries.begin() +10; i < file_entries.end(); ++i ) { DeleteFile( i->FileName.c_str() ); } } }
-
@wob sagte in Löschen von älteren Backupdateien:
In bash würde ich ja vorschlagen:
ls -t1 | tail -n +11 | xargs rm
Herzlichen Glückwunsch, du hast den output von
ls
geparsed und bist prompt in alle üblichen Fallen gestolpert. Was, wenn da Unterverzeichnisse drin sind? Was, wenn es da Dateien mit Leerzeichen oder anderen komischen Zeichen im Namen gibt?Stattdessen bitte
find
mit passenden Einschränkungen nutzen (Oder etwas abenteuerlicher: Nach demls
die Namen mit/
rausfiltern), und beim xargs mit korrekten Placeholders arbeiten.
-
@wob Das Programm zu schreiben ist eine Aufgabe, die mir gegeben wurde. Ergo die Sprache muss c++ sein.
-
@deamonwannabee sagte in Löschen von älteren Backupdateien:
@wob Das Programm zu schreiben ist eine Aufgabe, die mir gegeben wurde. Ergo die Sprache muss c++ sein.
Fühlst du dich deinen zukünftigen Herausforderungen gewachsen? Wie stellst du dir deine Zukunft vor?
-
Ich würde mir ganz spontan die Windows-API Funktionen raussuchen, die etwas mit Directorys und Files zu tun haben.
Eventuell würde ich auch mal eine Suchmaschine bemühen:
http://www.codebind.com/cpp-tutorial/cpp-program-list-files-directory-windows-linux/Das sollte erst einmal einen guten Ausgangspunkt für Dein Programm abgeben.
Danach könnte ich mich etwas mit den Zeit- und Datumsfunktionen beschäftigen und wie man ein einzelnes Datum vergleicht.Zum Schluß würde ich noch rausfinden wollen, wie man eine Datei löscht.
-
#include <cstdlib> #include <algorithm> #include <vector> #include <filesystem> namespace fs = std::filesystem; int main() { fs::path const directory{ "E:/" }; std::vector<fs::directory_entry>::size_type const num_files_to_keep{ 10 }; std::vector<fs::directory_entry> files; for (auto &entry : fs::directory_iterator{ directory }) if (entry.is_regular_file()) files.push_back(entry); if (files.size() <= num_files_to_keep) return EXIT_SUCCESS; std::sort(files.begin(), files.end(), [](fs::directory_entry const &lhs, fs::directory_entry const &rhs) { // return lhs.last_write_time().time_since_epoch() > rhs.last_write_time().time_since_epoch(); // siehe @wob ein Post drunter return lhs.last_write_time() > rhs.last_write_time(); } ); for (auto i{ num_files_to_keep }; i != files.size(); ++i) fs::remove(files[i].path()); }
-
@Swordfish sagte in Löschen von älteren Backupdateien:
return lhs.last_write_time().time_since_epoch() > rhs.last_write_time().time_since_epoch();
UUOTSE
(useless use of time since epoch, time_points können direkt verglichen werden)
(und man könnte überlegen, die Zeiten zu speichern und nicht bei jedem Vergleich neu zu ermitteln)
-
@wob sagte in Löschen von älteren Backupdateien:
(und man könnte überlegen, die Zeiten zu speichern und nicht bei jedem Vergleich neu zu ermitteln)
Afaik werden die sowieso nur beim iterieren vom FS gelesen. // edit: jein. Implementation defined. What shalls.