SdFat - howto move up a directory + how to iterate a directory?

Does anyone know if it is possible to move up a directory using SdFat?

I was hoping to use something like:

sd.chdir("..")

What I am wanting to do is to recurse the sub-directory tree and iterate through all the files. As an example for the following structure, want to work on all files under /subdir_A/, ie files 1, 2 and 3:

/subdir_A/
          sub-dir_AA /
                      sub-dir_AAA /
                                   file1

          sub-dir_AB /
                      file2
                      file3

I’m not sure, but for relative navigation you would need to change the working directory with each navigation step (e.g. sd.chdir("someDir", true)).

1 Like

@ScruffR, it looks like I will have to revert to reading the sub-dir name at each step (which is a can do and am doing anyhow) and using that to “grow” and “collapse” the path in a string. Not neat, but it will work…

Relative navigation might be worth adding as a feature request “issue” to the SdFat repo

Bill (@whg), any chance for that?

Good idea!

The other problem which is looming is moving across from sub-dir_AA to sub-dir_AB once you have gone down a branch, if you know what I mean.

The following gets us down the first branch all the way to the bottom (say sub-dir_AA) (good):

while (file.openNext(sd.vwd(), O_READ))
{
    if (file.isDir())
    {
	  file.getName(szSubDir, sizeof(szSubDir));
	  file.close();
	  sd.chdir(szSubDir);
	  sd.vwd()->rewind();
	  continue;
    }

    file.getName(szFileName, sizeof(szFileName));
    // .... do stuff 
    file.close();
}

The issue is how do you get to sub-dir_AB?

The ls() function is written as a recursive function that will visit all directory entries in the tree below the current directory.

You can implement a function like this by making the current file, ‘this’ in ls(), an argument of the function rather than as a member of the file class.

//------------------------------------------------------------------------------
bool FatFile::ls(print_t* pr, uint8_t flags, uint8_t indent) {
  FatFile file;
  if (!isDir()) {
    DBG_FAIL_MACRO;
    goto fail;
  }
  rewind();
  while (file.openNext(this, O_RDONLY)) {
    // indent for dir level
    if (!file.isHidden() || (flags & LS_A)) {
      for (uint8_t i = 0; i < indent; i++) {
        pr->write(' ');
      }
      if (flags & LS_DATE) {
        file.printModifyDateTime(pr);
        pr->write(' ');
      }
      if (flags & LS_SIZE) {
        file.printFileSize(pr);
        pr->write(' ');
      }
      file.printName(pr);
      if (file.isDir()) {
        pr->write('/');
      }
      pr->write('\r');
      pr->write('\n');
      if ((flags & LS_R) && file.isDir()) {
        file.ls(pr, flags, indent + 2);
      }
    }
    file.close();
  }
  if (getError()) {
    DBG_FAIL_MACRO;
    goto fail;
  }
  return true;

 fail:
  return false;
}

Implementing relative navigation is not easy for FAT. There is a … entry in FAT16/FAT32 but it is a copy of the 8.3 directory so then you must do a search for the actual directory.

exFAT eliminated the … entry so I gave up on relative navigation for SdFat V 2.0 which is now in beta.

The best way is to implement relative navigation is to maintain the entire path in memory as an array of open files. This is expensive in memory and code and my top priority is to support Uno, the classic Arduino.

3 Likes

@whg, thanks very much for your response (and your great efforts on the SDFAT library).

Now understand the issues with the relative navigation - so I will drop this approach.

I will implement a solution using your ls() code as a sample which will hopefully lead to closing this ticket.

Back soon…

@whg, happy to report that modifying your ls() code for my use case worked a treat.

It successfully iterated through all the sub-directories and files under a specified directory.

Case closed with thanks!

1 Like