How to get name of directory when directory name is unknown? SdFat

Hi!

Preface:
i have been reading a bunch, and finally excited to having some vague understanding of how to use a few basic sdfat functions. I think as a newb I had some trouble with a bit of the "::" and "->" and other more experienced c++ nomenclature. Yeah, I don't mean to blame the author, obviously the user should know how to read, and it's a learning opportunity for me.

Main point

I'm trying to make a function where I search the root of my sdcard, and check for directories. I want to name the directories, and eventually check each directory to see if it has a "cfg.txt" in it. If it does, then it's a "username" directory, and that'll be a location to log files in.

A relevant thread seems: http://forum.arduino.cc/index.php/topic,226037.0.html, but it operates on the assumption that the directory name past root is known.

Where I'm at
I think I have, at least, 'getfilename' and 'dirname' functions sort of working. I modified the "openNext" example sketch, so I do properly cycle through all of the directories and files in the root.

However, using getfilename and dirname just return '/' for me, since my working directory is the root, I think. But I don't know how to get into the directories that I find, so as to run dirname and find their name. I can use chdir only if I know what the directory name is, but I don't always know that. I could include a file in the root with "users.csv" or something, but that seems like a crude solution. This function should only be run once per startup, so it doesn't need to be fast.

Any help or tips would be greatly appreciated. I think whatever I'm missing

Code below: I pulled out a few debug serial.print()s, and a couple small things for clarity.

void findDirectories(){
  //Start in root. 
  // Change current directory to root.
  if (!sd.chdir()) Serial.println(F("chdir to root failed."));

  uint8_t entryLimit = 21;
 
  char UserSet[entryLimit][14];

  uint8_t i=0;

  // open next file in root.  The volume working directory, vwd, is root
  while (myFile.openNext(sd.vwd(), O_READ)) {
    if (myFile.isDir()) {
      // Indicate a directory.

      char name[13];
      // name for current working directory
      myFile.cwd()->getFilename(name);
      Serial.print(F("Name is:/"));
      Serial.println(name);
      Serial.print(F("Or...: "));
      dir_t dir;
      myFile.dirName(dir, name);
      Serial.println(name);

//Neither dirName nor getFileName give me anything other than "/" when these folders have real names. 

      strlcpy(UserSet[i],name,sizeof(UserSet[i]));
     //Later, check that each directory has a cfg.txt before deciding it's part of the UserSet
      i = i++;
    }

    else{ //Other files, which are not directories, remove eventually
    }
    myFile.close();
  }

  Serial.println(F("Done with FindDirectories!"));
  Serial.println(F("printing list: "));
//Seems I can't just print a 2d char array, so I print it piecewise.
  for(i = 0;i<entryLimit;i++){
  Serial.println(UserSet[i]);}
}

I should add, that my sd card is basically this:
"1.csv, 2.csv, 3.csv, 5.txt, folder1,folder2,folder3,folder5" and within 3 of the 4 folders I have a cfg.txt file, but nothing else.

I'm pretty much at a loss. So if you're one of the 60+ and rising viewers who have seen this, and you have any hints or suggestions, I'm all ears :)!

Thanks.

I have not used the SD library but a quick look at the reference page seem to point to you using FileOpenNextFile and isDirectory to determine if next file is a directory or file. You can then extract the directory name using .name (all according to the reference)

Riva:
I have not used the SD library but a quick look at the reference page seem to point to you using FileOpenNextFile and isDirectory to determine if next file is a directory or file. You can then extract the directory name using .name (all according to the reference)

Thanks Riva!

Yeah, I actually do use fileOpenNext, and then isDirectory in the code posted. It seems that then using getFilename, or dirName, I still only get "/" as the name, so I suspect a failure in my procedure. It acts as if I am still in root, even though the true to isDirectory shows clearly that my fileOpenNext procedure does know it's looking at a directory, and not a file.

I'll try a few more things.

I have verified that I'm looking through all the files and directories, but I haven't tried pulling the names from the non-directories (i.e, the files.) maybe that will work.

Have you tried running the example on the reference page I linked too, it's using Serial.print(entry.name()); to print the file/directory name.
You code snippet does not show if your using the standard SD library as the function names do not seem to match.
isDirectory() vs isDir()

I am using SdFat, not the standard Sd.h library. Is that the difference you are mentioning? Perhaps I was not clear enough, because I may have only mentioned this in my title. I am sorry for any confusion that may have caused

Something that drew me back to this page: It occurred to me that I am declaring

char name[13] locally in my function. It may be that I need to be declaring it globally, since the function does not "return" name, it seems to modify it within the function. I'm not certain.

Kinnishian:
I am using SdFat, not the standard Sd.h library. Is that the difference you are mentioning? Perhaps I was not clear enough, because I may have only mentioned this in my title. I am sorry for any confusion that may have caused
Also my bad as I only tend to skim titles, I now see it refers to SdFat.
Is SdFat an extension of SD or a separate library? They both seem to reside in the same library folder. If it's an extension then can you mix and match SD & SdFat functions?

Something that drew me back to this page: It occurred to me that I am declaring
char name[13] locally in my function. It may be that I need to be declaring it globally, since the function does not "return" name, it seems to modify it within the function. I'm not certain.
I had a look at the original SdFat examples/documentation that don't seem to be included in the standard Arduino library and it might be worth looking at this sketch. Other than that I'm not really helping. I will have to dust off my Ethernet shield and play with the SD card functions at some point.

Here is a function that lists all directories on an SD. You need to add what you need to find files in each directory.

#include <SdFat.h>
// SD chip select pin
const uint8_t chipSelect = SS;

// file system object
SdFat sd;
//------------------------------------------------------------------------------
void printDirs(SdBaseFile* dir, uint8_t indent) {
  SdBaseFile subDir;
  // Indent for subdir level
  for (uint8_t i = 0; i < indent; i++) Serial.write(' ');

  // You could use bool getFilename(char* name) here to get the text.
  dir->printName(&Serial);
  Serial.println();
  dir->rewind();
  while (subDir.openNext(dir, O_READ)) {
    if (subDir.isDir()) printDirs(&subDir, indent + 3);
    subDir.close();
  }
}
//------------------------------------------------------------------------------
void setup() {
  Serial.begin(9600);
  while (!Serial) {} // wait for Leonardo
  delay(1000);
  
  if (!sd.begin(chipSelect)) sd.initErrorHalt();
  printDirs(sd.vwd(), 0);
  Serial.println("Done!");
}
void loop() {}

Here is a tree list of an SD done on a PC (quote is not spacing these listings correctly):

H:.
????DIR1
? ????DIR1A
? ????DIR1B
????DIR2
????DIR2A
????DIR2B
????DIR2B1
????DIR2B2

Here is output from the above program

/
DIR1
DIR1A
DIR1B
DIR2
DIR2A
DIR2B
DIR2B1
DIR2B2
Done!

Thanks!

I have it working now with the following code, at least for the basic case without that cfg.txt stuff I mentioned. That's next.

void printDirs(SdBaseFile* dir, uint8_t indent) {
  SdBaseFile subDir;

  // Indent for subdir level
  for (uint8_t i = 0; i < indent; i++) Serial.write(' ');

  Serial.println(F("Found directory"));
  char name[13];
  // name for current working directory
  dir->getFilename(name);

  uint8_t z = 0;  // Here I in a crude method check to see if there isn't already a name in the UserSet list. 
  while (strcmp(UserSet[z],Empty)){  //I tripped up for a while, because I was trying to compare directly with != instead of strcmp
    z++;
  } // i.e, Counter past the UserSet entries that are taken. 
  
 
  //strlcpy(disp[0], inString, sizeof(disp[0])) 
  strlcpy(UserSet[z],name,sizeof(UserSet[z]));
  //Later, make safties for directory. require a cfg.txt


  dir->rewind();
  while (subDir.openNext(dir, O_READ)) {
    if (subDir.isDir()) printDirs(&subDir, indent + 3);
    subDir.close();
  }

  Serial.println(F("Done with FindDirectories!"));
  Serial.println(F("printing list: "));
  for(z = 0;z<entryLimit;z++){
    Serial.println(UserSet[z]);
  }
}

Now, to be honest, I don't full understand how this code works. I think I need to understand better what the 'dir' means, and what '->' means. I don't know exactly how to figure that out, since last time I searched for -> it was said to be some form of operator
"Structure dereference ("member b of object pointed to by a")"
And to be honest I don't really grasp what that is saying.

But I've also already been helped alot, so I really appreciate that! Thank you.