SdFat icon indicating copy to clipboard operation
SdFat copied to clipboard

Migration to 2.* .. how to use chdir() when there's no vwd() or cwd()

Open nealcrook opened this issue 3 years ago • 3 comments

(This is a similar question to #288

Hi Bill,

thanks for creating, documenting and sharing SdFat. I have a question about migration from 1.* to 2.*. Previously I did this:

SdFat SD;
.
.
.
SD.begin(...);
if (condition) {
   SD.chdir("MYDIR");
}
else {
  SD.chdir("MYOTHERDIR");
}

and all through my code I did stuff like:

handle.open("MYFILE");

in the knowledge that MYFILE would be created in The Right Place

At one point, I want to list the contents of the directory in use (MYDIR or MYOTHERDIR) and for various reasons don't want to use the in-built format but to format the output myself, so I did this:

working_dir = SD.vwd();
working_dir->rewind();
while (handle.openNext(working_dir, O_RDONLY)) {
 ...
}

With release 2.* the absence of vwd()/cwd() means that I cannot use openNext in this way. It looks like, to use it, I need to not use chdir, but to track the cwd myself and use it for every file operation:

SD.begin(...);
if (condition) {
   working_dir.open("MYDIR");
}
else {
  working_dir.open("MYOTHERDIR");
}

and all through my code do stuff like:

handle.open(&working_dir, "MYFILE");

Just so that, eventually, I can do this:

working_dir.rewind();
while (handle.openNext(&working_dir, O_RDONLY)) {
 ...
}

Your example DirectoryFunctions/DirectoryFunctions.ino seems to acknowledge this by the way it only uses openNext after explicitly opening a directory, where earlier in the code it was using chdir().

So, in summary, my questions are:

  • is there a clean way to use openNext in conjunction with the current working directory
  • (if not) is there a reason for the removal of vwd()/cwd() given their usefulness in this example? The Old Way seems cleaner because the global state (the current working directory) was hidden within the SD's state whereas the New Way requires me to track it as a new piece of global state within my code

thanks and regards,

Neal

nealcrook avatar Dec 31 '21 12:12 nealcrook

I made vwd private since internal use conflicts with use in some application.

There no longer is a single cwd since it can't exist for all combinations of FAT/exFat volumes since they are different class types.

I have implemented a simple solution in SdFat-beta that will soon be in the release version.

A cwd exists for each volume type. here is an example for SdFat/File.

// example without error checks and uses simple default arguments.
#include "SdFat.h"
// sd, cwd and file must be compatible types. 
SdFat sd;
File cwd;
File file;

void setup() {
  Serial.begin(9600);
  sd.begin();
  sd.chdir("MyDir");
  cwd.openCwd();
  while(file.openNext(&cwd)) {
    file.printName(&Serial);
    Serial.println();
    file.close();
  }
  Serial.println("Done");
}
void loop() {}

Here is the output:

file1.txt
file2.txt
Done

greiman avatar Dec 31 '21 17:12 greiman

Hi Bill, thank you for your suggestion; it looks like a good, clean solution to my problem. I have downloaded SdFat-beta. I will test it with my application and report back. regards, Neal.

nealcrook avatar Jan 01 '22 15:01 nealcrook

Thanks, it would help to include this tidybit of information on the examples.

Here is an implementation for the ls command that required the cwd functionality:

// prints a line of text
void func_ls(char *args, Stream *response ){
  File dir;
  File file;

  // open the current directory
  if (!dir.openCwd()){
    response -> println("Failed to open the directory");
    return;
  }

  while (file.openNext(&dir, O_RDONLY)) {
    //String fileName = file.name();

    char fileName[13];
    size_t len = file.getName(fileName, sizeof(fileName));

    if(file.isDirectory()){
      response -> print(fileName);
      response -> println("/");
    }else{
      response -> println(fileName);
    }
    file.close();
  }
}

maxbrito500 avatar Mar 28 '23 10:03 maxbrito500