Home > other >  c filesystem, get files in directory alphabetically, rename inputs
c filesystem, get files in directory alphabetically, rename inputs

Time:12-23

I have the following code:

/*
This function conditions folders into a standard format with the following specifications
The first file in the folder to render has an index starting at 0
with the name of outPutName[Index].fileExtension  dataType is preserved 
*/
void vCanvas::conditionFolder(vizModule target){
  vector<string> fileNames;
  int index = 0;
  string outputName = "output";
  string oPath = target.path;
  string temp;
  cout << "vCanvas::conditionFolder is processing" << oPath << endl;
  //https://en.cppreference.com/w/cpp/filesystem/rename
  for (const auto & entry : fs::directory_iterator(oPath)){
    if (entry.is_regular_file()){
      temp = entry.path().stem().string();
      cout << oPath temp << " modified to " << oPath (outputName to_string(index) "." target.dataType) << endl;
      fs::rename(oPath temp, oPath (outputName to_string(index) "." target.dataType));
      index  ;
    }
  }
}

I was hoping fs::directoryiterator would give me entrys in alphabetical order and it doesn't. I am getting 0007.png before 0001.png, which is unworkable. Is there any simple solution that will let me get all files in a folder, in alphabetical order, and rename them?

Second iteration on the above code, using std::sort

//see https://www.cplusplus.com/reference/algorithm/sort/
bool alphabetSort(string i, string j){
  int val = i.compare(j);
  if (val == -1) {return true;}
  else if (val == 1) {return false;}
  else {return false;}
}

/*
This function conditions folders into a standard format with the following specifications
The first file in the folder to render has an index starting at 0
name of outPutName.  dataType is preserved
*/
void vCanvas::conditionFolder(vizModule target){
  string outputName = "output";
  string oPath = target.path;
  string temp;
  vector<string> fileStrings;
  cout << "vCanvas::conditionFolder is processing" << oPath << endl;
  //https://en.cppreference.com/w/cpp/filesystem/rename
  for (const auto & entry : fs::directory_iterator(oPath)){
    if (entry.is_regular_file()){
      temp = entry.path().stem().string();
      fileStrings.push_back(temp);
    }
  }
  for (int i = 0; i < fileStrings.size(); i  ){
    cout << fileStrings[i] << ",";
  }
  sort(fileStrings.begin(), fileStrings.end(),alphabetSort);
  cout << "Directory sorted" << endl;
  for (int i = 0; i < fileStrings.size(); i  ){
    cout << fileStrings[i] << ",";
  }
  cout << endl;
  for (int k = 0; k < fileStrings.size(); k  ){
    temp = fileStrings[k];
    cout << oPath temp << " modified to " << oPath (outputName to_string(k) "." target.dataType) << endl;
    fs::rename(oPath temp, oPath (outputName to_string(k) "." target.dataType));
  }
}

Which gives

vCanvas::conditionFolder is processing./unit_tests_folder/testpng1/
0007,0014,0018,0008,0012,0002,0005,0010,0016,0003,0001,0006,0015,0019,0017,0004,0011,0013,0009,0020,
0007,0009,0008,0002,0005,0004,0003,0001,0006,0014,0013,0011,0017,0019,0015,0016,0010,0012,0018,0020,

CodePudding user response:

I wrote and ran unit tests on this function, which does what I want, which, in specific, is to first sort alphabetically, but then, if the program is comparing 2 digits, to take the smaller size string. This works for my purposes, which is simply to handle consistent but arbitrarily named series of .pngs and turn them into a standardized format.

bool alphaNumerSort(string i, string j){
  string shorterStr;
  (i.size() <= j.size()) ? shorterStr = i : shorterStr = j;

  for (int k = 0; k < shorterStr.size(); k  )
  {
    if (i[k] != j[k] && isdigit(i[k]) && isdigit(j[k]) ) {
      if (i.size() == j.size()) {
        return i[k] < j[k];
      }
      return (i.size() < j.size());
    }
    if (i[k] != j[k]) {
      return i[k] < j[k];
    }
  }
  return false;
  //returns true if i is alphabetically before j
}
  • Related