ulfben

FilteredDeleter

Jan 2nd, 2018
128
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // FilteredDeleter deletes all files in the target folder, which does not exist in the source folder.
  2. // It only looks at file names and ignores file extension.
  3.  
  4. // It solves a niche problem for me, after photographing big events.
  5. // I shoot JPG+RAW. RAW files are enormously slow to flip through.
  6. // Thus, when I manually cull the set - throwing out all unusable photos -
  7. // -I only look at the JPGs. Leaving me with:
  8. //    -a (source) folder of curated (JPG) files (<1000s of files, <10GB)</li>
  9. //    -a (target) folder with *all* (RAW) files (>1000s of files, >50GB)</li>
  10. // This program deletes all the unneeded RAW files.
  11. // TODO: implement the command line interface
  12. #include <algorithm>
  13. #include <filesystem>
  14. #include <cctype>
  15. #include <iterator>
  16. #include <iostream>
  17. #include <string>
  18. #include "ProgramOptions.h"
  19. using namespace std::string_literals;
  20. namespace fs = std::experimental::filesystem;
  21. using PathList = std::vector<fs::path>;
  22. PathList getFileList(const fs::path& dir); //returns a sorted list of file paths
  23. PathList getDifference(const PathList& source, const PathList& target);
  24. bool userConfirm(const std::string& message, const std::string& yes = "y"s);
  25. void deleteFiles(const PathList& toRemove);
  26. template<typename C, typename T = fs::path> void printEach(const C& v);
  27.  
  28. int main(int argc, char* argv[]){
  29.     const ProgramOptions opts(argc, argv);     
  30.     const auto source = fs::path{R"(Y:\Temp\WeddingPhotosChosen)"}; //Q&D: hardcoding paths...
  31.     const auto target = fs::path{R"(Y:\Temp\WeddingPhotosRAW)"}; //TODO: use the ProgramOptions command line interface
  32.     const PathList sourceFiles = getFileList(source);
  33.     const PathList targetFiles = getFileList(target);
  34.     const PathList toRemove = getDifference(sourceFiles, targetFiles); 
  35.     printEach(toRemove);       
  36.     if(userConfirm("Press Y to delete these files."s)){
  37.         deleteFiles(toRemove);
  38.     }
  39.     userConfirm("Done! Double-check the error output\n\tbefore you press any key to quit."s);
  40.     return 0;
  41. }
  42.  
  43. PathList getDifference(const PathList& sourceFiles, const PathList& targetFiles){
  44.     //Copies the elements from the sorted range [targets)
  45.     //which are not found in the sorted range [source)
  46.     //to the list toRemove.
  47.     PathList toRemove;
  48.     std::set_difference(targetFiles.begin(), targetFiles.end(),
  49.         sourceFiles.begin(), sourceFiles.end(),
  50.         std::inserter(toRemove, toRemove.begin()),
  51.         [](const fs::path& source, const fs::path& target){
  52.             return source.stem() < target.stem(); //comparing only filenames
  53.         }
  54.     );
  55.     return toRemove;
  56. }
  57. template<typename C, typename T>
  58. void printEach(const C& v){
  59.     std::copy(std::begin(v), std::end(v), std::ostream_iterator<T>{std::cout, ",\n"});
  60.     std::cout << '\n';
  61. }
  62. PathList getFileList(const fs::path& dir){
  63.     PathList out;
  64.     if(!fs::exists(dir) || !fs::is_directory(dir)){
  65.         return out;
  66.     }
  67.     for(const auto& entry : fs::directory_iterator(dir)){
  68.         if(fs::is_regular_file(entry.status())){
  69.             out.push_back(entry.path());
  70.         }
  71.     }
  72.     std::sort(out.begin(), out.end());
  73.     return out;
  74. }
  75. void deleteFiles(const PathList& toRemove){
  76.     for(const auto& file : toRemove){
  77.         if(!is_regular_file(file)){
  78.             std::cerr << "Warning: skipping non-file: "s << file.filename().string();
  79.             continue;
  80.         }
  81.         if(!fs::remove(file)){
  82.             std::cerr << "Error: unable to delete: "s << file.filename().string();
  83.         }
  84.     }
  85. }
  86. bool userConfirm(const std::string& message, const std::string& yes){
  87.     std::cout << message << "\n";
  88.     std::string response;
  89.     std::getline(std::cin, response);
  90.     std::transform(response.begin(), response.end(), response.begin(),
  91.         [](unsigned char c){ return std::tolower(c, std::locale()); }
  92.     );
  93.     return response == yes;
  94. }
RAW Paste Data

Adblocker detected! Please consider disabling it...

We've detected AdBlock Plus or some other adblocking software preventing Pastebin.com from fully loading.

We don't have any obnoxious sound, or popup ads, we actively block these annoying types of ads!

Please add Pastebin.com to your ad blocker whitelist or disable your adblocking software.

×