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 entry
s 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
}