SD Card reads 212 files

Was wondering why I can only get 212 files listed before the Arduino freezes

Modified the SD list files example to print out path, and file read content.

r key to only list files
y key to list file and its contents

UNO board.

 /*
  SD card basic file example
 
 This example shows how to create and destroy an SD card file 	
 The circuit:
 * SD card attached to SPI bus as follows:
 ** MOSI - pin 11
 ** MISO - pin 12
 ** CLK - pin 13
 ** CS - pin 4
 
 created   Nov 2010
 by David A. Mellis
 modified 9 Apr 2012
 by Tom Igoe
 
 This example code is in the public domain.
 	 
 */
//#include <SPI.h>
#include <SD.h>

File root;
String directoryname = "/";
String lastdirectory = "";
bool noreadfile = false;
int counter = -1;


void setup()
{
  // Open serial communications and wait for port to open:
  Serial.begin(2000000);
   while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }


  Serial.print("Initializing SD card...");
  // On the Ethernet Shield, CS is pin 4. It's set as an output by default.
  // Note that even if it's not used as the CS pin, the hardware SS pin 
  // (10 on most Arduino boards, 53 on the Mega) must be left as an output 
  // or the SD library functions will not work. 
  pinMode(10, OUTPUT);

  if (!SD.begin(10)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");
  Serial.println("Send X to exit, Send R for readonly, Continue full read (Y/N)? ");
}

void loop()
{
  // nothing happens after setup finishes.


  char inChar = Serial.read();
  if (inChar == 'Y' || inChar == 'y' || inChar =='r' || inChar == 'R'){

  if (inChar =='r' || inChar == 'R'){ noreadfile = true; }
  
  root = SD.open("/");
  
  File entryx = root.openNextFile();
  lastdirectory = entryx.name();
  //Serial.println("directory: " + lastdirectory);
  entryx.close();
  root.rewindDirectory();
  counter = 0;   
  //noInterrupts();
  printDirectory(root, 0);
  root.close();  
  Serial.print("done ");
  Serial.print( counter );
  Serial.println("!");
  }
  
}

void printDirectory(File dir, int numTabs) {
   while(true) {
     
     
     File entry =  dir.openNextFile();
 
     char inCharx = Serial.read();
     if (inCharx == 'X' || inCharx == 'x'){
       break;  
     }
     if (! entry) {
       // no more files
       //Serial.println("**nomorefiles**");
       break;
     }
     //for (uint8_t i=0; i<numTabs; i++) {
     //  Serial.print('\t');
     //}
     //Serial.print(entry.name());
     //Serial.print("------");
     //Serial.print(numTabs);

     if (entry.isDirectory()) {
       if (numTabs != -1 ){//Serial.print("---1---");
        if (directoryname=="" || numTabs == 0){//Serial.print("---2---");
          directoryname = '/' + lastdirectory + '/' ;
          if (lastdirectory == ""){directoryname = entry.name();directoryname = '/' + directoryname;/*Serial.print("---3---");*/}else{lastdirectory = "";/*Serial.print("---3a---");*/}
          
          }else{           // Serial.print("---4---");
          directoryname = '/' + directoryname + '/' + entry.name();
          }
       
       }else{//Serial.print("---5---");
       directoryname = ('/' + lastdirectory + '/').c_str();
       lastdirectory = "";
       }
       //Serial.println("/");
       directoryname.replace("//","/");
       if (lastdirectory == directoryname){lastdirectory="";}else{
       lastdirectory = directoryname;}
       printDirectory(entry, numTabs+1);
     } else {
       // files have sizes, directories do not
       //Serial.print("\t\t");
       //Serial.println(entry.size(), DEC);
      //directoryname.replace("//","/");
      
if(numTabs == 0){ directoryname = ""; lastdirectory = ""; }
         String dfilename = ( directoryname + '/' + entry.name() ).c_str();
             Serial.print( "(" );
             Serial.print( dfilename );
             Serial.println( ")" );
 counter++;
 entry.close(); //moved this here - inside the while loop, dont do root ?!?
   if(!noreadfile){   
      
       File dataFile = SD.open(dfilename, FILE_READ);
 //     File dataFile = SD.open(entry.name());

  // if the file is available, write to it:
  if (dataFile) {
    while (dataFile.available()) {
      Serial.write(dataFile.read());
    }
    dataFile.close();
  }  
  // if the file isn't open, pop up an error:
  else {

if(dfilename!=""){Serial.print( dfilename );
}else{
Serial.print( "Dir" );
}
    
    Serial.println(" error opening for reading...");
  } 

   }//!noreadfile
       
    // entry.close(); //moved this here - inside the while loop, dont do root ?!?
     }
     //entry.close();
   }
//Serial.println("ending printdirectory"); //this line results in 193 files read
}

I would hazard a guess that it may be to do with the use of the String class and subsequent memory fragmentation leading to the UNO running out of RAM.

I made another test but this time with the function variable of dfilename as a global string and was able to list 241 files, so it would seem the String class is giving me issues. Thanks Mark for the tip.

Have also ordered a MEGA :slight_smile:

Re-ran the test because I had damaged some of the code making up the path output, 207 files listed with the function variable of dfilename as a global string.

Using the F() macro when printing text literals will free up a bit of memory.

  Serial.print(F("Initializing SD card...")); 
//stores text in program memory instead of ram

Thanks David, I ran the changes using F() on all Serial.print's and got a few more bytes. 1133 bytes, instead of 999 bytes to start with. Resulted in 242 files listed...

1175 bytes instead of 1133 (I found I forgot to F() four lines - so every line possible is now using F())

266 Files listed

Added two more lines to setup function above Serial.print,

directoryname.reserve(29);
lastdirectory.reserve(30);
Serial.print(F("Initializing SD card..."));

345 files listed, with values of 29-31.

If I close all the entry objects then I can use the R key again, solving the freezing issue. Only 379 files are listed (last 11 files seem to have the wrong path in my prints). Some times it will output that 391 files were listed however its not IMHO the truth...

Sorry about the messy comments but this is my playing around sketch, a lot of code will never see the processor but its included none the less.

Still waiting for the MEGA to arrive

 /*
  SD card basic file example
 
 This example shows how to create and destroy an SD card file 	
 The circuit:
 * SD card attached to SPI bus as follows:
 ** MOSI - pin 11
 ** MISO - pin 12
 ** CLK - pin 13
 ** CS - pin 4
 
 created   Nov 2010
 by David A. Mellis
 modified 9 Apr 2012
 by Tom Igoe
 
 This example code is in the public domain.
 	 
 */
#include <WString.h>
#include <SPI.h>
#include <SD.h>

File root;

String directoryname = "";
String lastdirectory = "";
//String dfilename = ""; //results in 207 files
//String dfilename __attribute__ ((section (".noinit"))); //results in 242 files
bool noreadfile = false;
int counter = -1;


void setup()
{
  // Open serial communications and wait for port to open:
#ifdef ARDUINO
if(ARDUINO <= 105){  //for IDE 1.0.5
  Serial.begin(115200); 
}else{  //latest stable version 1.8.19
  Serial.begin(2000000);
}
#elif
  Serial.begin(9600);
#endif

while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }

directoryname.reserve(109);  //109-120  // 356 files (see 380 files comment line)
lastdirectory.reserve(110);

Serial.println( freeMemory() );
Serial.print(F("Initializing SD card..."));
  // On the Ethernet Shield, CS is pin 4. It's set as an output by default.
  // Note that even if it's not used as the CS pin, the hardware SS pin 
  // (10 on most Arduino boards, 53 on the Mega) must be left as an output 
  // or the SD library functions will not work. 
  pinMode(10, OUTPUT);

  if (!SD.begin(10)) {
    Serial.println(F("initialization failed!"));
    return;
  }
  Serial.println(F("initialization done."));
  Serial.println(F("Send X to exit, Send R for readonly, Continue full read (Y/N)? "));
}

void /*__attribute__ ((noinline))*/ loop()
{
  // nothing happens after setup finishes.


  char inChar = Serial.read();
  if (inChar == 'Y' || inChar == 'y' || inChar =='r' || inChar == 'R'){

  if (inChar =='r' || inChar == 'R'){ noreadfile = true; }
  
  root = SD.open(""); //was SD.open("/");
  
  File entryx = root.openNextFile();
  lastdirectory = entryx.name();
  //Serial.println("directory: " + lastdirectory);
  entryx.close();
  root.rewindDirectory();
  counter = 0;   
  //noInterrupts();
  Serial.println( freeMemory() );
  printDirectory(root, 0);
  root.close();  
  Serial.print(F("done "));
  Serial.print( counter );
  Serial.println(F("!"));
  }
  
}

//__attribute__((optimize("O2"))) 
void printDirectory(File dir, int numTabs) {
  while(true) {
     
     
     File entry =  dir.openNextFile();
 
     char inCharx = Serial.read();
     if (inCharx == 'X' || inCharx == 'x'){
       break;  
     }
     if (! entry) {
       // no more files
       //Serial.println("**nomorefiles**");
      // if(numTabs==0){dir.close();}
       //return false;
      // Serial.println(numTabs);
      // numTabs--;
       
       break;
     }
     //for (uint8_t i=0; i<numTabs; i++) {
     //  Serial.print('\t');
     //}
     //Serial.print(entry.name());
     //Serial.print("------");
     //Serial.print(numTabs);

     if (entry.isDirectory()) {
       if (numTabs != -1 ){//Serial.print("---1---");
        if (directoryname=="" || numTabs == 0){//Serial.print("---2---");
          directoryname = '/' + lastdirectory + '/';
          if (lastdirectory == ""){directoryname = entry.name();directoryname = '/' + directoryname;/*Serial.print("---3---");*/}else{lastdirectory = "";/*Serial.print("---3a---");*/}
          
          }else{           // Serial.print("---4---");
          directoryname = '/' + directoryname + '/' + entry.name();
          }
       
       }else{//Serial.print("---5---");
       directoryname = ('/' + lastdirectory + '/').c_str();
       lastdirectory = "";
       }
       //Serial.println("/");
       directoryname.replace("//","/");
       if (lastdirectory == directoryname){lastdirectory="";}else{
       lastdirectory = directoryname;}
       if(entry.name() != ""){
       printDirectory(entry, numTabs+1);
       }else{break;}
#ifdef ARDUINO 
//Serial.println(ARDUINO);
if(ARDUINO <= 105){
        const int fnumTabs = numTabs+1;
        if(fnumTabs!=0 && entry){entry.close();} // has 77 files :-(
}else{

      const int fnumTabs = numTabs+1;
        if((fnumTabs!=0 /*|| numTabs==0*/)&&entry){if(fnumTabs!=0){if(dir.name()!=""){entry.close();}}else{if(dir.name()!=""){entry.close();break;}}} // 380 files but with errors in output, see 356 files comment line above - everything past the else statement is code thats never seen by the processor
  
}
#endif
     } else {
       // files have sizes, directories do not
       //Serial.print("\t\t");
       //Serial.println(entry.size(), DEC);
      //directoryname.replace("//","/");
      //Serial.println(dir.name());Serial.println(root.name());
if(numTabs == 0 && dir.name()!=entry.name()){ directoryname = ""; lastdirectory = ""; }


      /*const*/ String dfilename /*PROGMEM*/ =  directoryname + '/' + entry.name();
     if (dfilename!=""){  
      
      dfilename.replace("//","/");

Serial.flush();
delay(10);    //100 = 379 files; VERY IMPORTANT LINE, wait for PC output to catch up with serial USB - otherwise garbage is seen on pc output
if(ARDUINO > 105){  
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }
}
             
             Serial.print( F("(") );
             Serial.write( dfilename.c_str() );
             Serial.println( F(")") );
             
             
 counter++;
 if(entry){entry.close();} //moved this here - inside the while loop, dont do root ?!?
     }else{break;}
     
   if(!noreadfile){   
      
       File dataFile = SD.open(dfilename.c_str(), FILE_READ);
 //     File dataFile = SD.open(entry.name());

  // if the file is available, write to it:
  if (dataFile) {
    while (dataFile.available()) {
      Serial.write(dataFile.read());
    }
    dataFile.close();
  }  
  // if the file isn't open, pop up an error:
  else {

if(dfilename!=""){Serial.print( dfilename );
}else{
Serial.print( F("Dir") );
}
    
    Serial.println( F(" error opening for reading..."));
  } 

   }//!noreadfile
 
  //   entry.close(); //moved this here - inside the while loop, dont do root ?!?
     }
     //entry.close();
   }
//Serial.println("ending printdirectory"); //this line results in 193 files read
//Serial.println( freeMemory() );

}

#ifdef __arm__
// should use uinstd.h to define sbrk but Due causes a conflict
extern "C" char* sbrk(int incr);
#else  // __ARM__
extern char *__brkval;
#endif  // __arm__

int freeMemory() {
  char top;
#ifdef __arm__
  return &top - reinterpret_cast<char*>(sbrk(0));
#elif defined(CORE_TEENSY) || (ARDUINO > 103 && ARDUINO != 151)
  return &top - __brkval;
#else  // __arm__
  return __brkval ? &top - __brkval : &top - __malloc_heap_start;
#endif  // __arm__
}

@markd833 nailed it in reply #2 - your heavy use of String objects is almost certainly fragmenting your memory. See if you can adapt to using plain old C strings instead.

Do you have any idea what the maximum depth of folders would be? Hard to convert to char arrays when the maximum file path length is unlimited.

No real idea of folder depth on SD Card (its an old backup made with windows where I just dumped folders and files); I would suspect the depth is well past 8.3 recommendations in parts but not unlimited. I count 1 to 12 folders deep so far with the Arduino DUO but I do notice the 10th folder isnt to 8.3 name standards in the output.

If I recall correctly, under windows there was a total path length limit of 255 characters. Not sure if this is the case in newer versions of windows.

Also, if failing memory serves, besides the long filenames, the filesystem also stored a short 8.3 version of the same filename.

After many attempts, the code above has errors in the path generation. I also lost the SDCard to a failure on init.

I dumped a old copy of filezilla on the SDCard and then 4 text files in the root; I can list a max of 17 files with the Arduino example, or with my modified play things (one for MEGA is below, sorry about the strings - wont work on UNO at this time; I only wrote for 8 directorys deep so have a few more to go to reach 256 chars)

Also the MEGA has arrived :slight_smile:

 /*
  SD card basic file example
 
 This example shows how to create and destroy an SD card file 	
 The circuit:
 * SD card attached to SPI bus as follows:
 ** MOSI - pin 11
 ** MISO - pin 12
 ** CLK - pin 13
 ** CS - pin 4
 
 created   Nov 2010
 by David A. Mellis
 modified 9 Apr 2012
 by Tom Igoe
 
 This example code is in the public domain.
 	 
 */

#include <SD.h>

File root;
static int counter;
String lastentryname01;
String lastentryname0;
String lastentryname1;
String lastentryname2;
String lastentryname3;
String lastentryname4;
String lastentryname5;
String lastentryname6;
String lastentryname7;
String lastentryname8;

void setup()
{
  // Open serial communications and wait for port to open:
#ifdef ARDUINO
if(ARDUINO <= 105){  //for IDE 1.0.5
  Serial.begin(115200); 
}else{  //latest stable version 1.8.19
  Serial.begin(2000000);
}
#elif
  Serial.begin(9600);
#endif

   while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }

Serial.println( freeMemory() );
Serial.print(F("Initializing SD card..."));
  // On the Ethernet Shield, CS is pin 4. It's set as an output by default.
  // Note that even if it's not used as the CS pin, the hardware SS pin 
  // (10 on most Arduino boards, 53 on the Mega) must be left as an output 
  // or the SD library functions will not work. 
  pinMode(SS, OUTPUT);

  if (!SD.begin(SS)) {
    Serial.println(F("initialization failed!"));
    return;
  }
  Serial.println(F("initialization done."));
  Serial.println(F("Send X to exit, Send R for readonly, Continue full read (Y/N)? "));

lastentryname01.reserve(1);
lastentryname0.reserve(8);
lastentryname1.reserve(8);
lastentryname2.reserve(8);
lastentryname3.reserve(8);
lastentryname4.reserve(8);
lastentryname5.reserve(8);
lastentryname6.reserve(8);
lastentryname7.reserve(8);
lastentryname8.reserve(8);

}

void loop()
{
  // nothing happens after setup finishes.
  char inChar = Serial.read();
  if (inChar == 'Y' || inChar == 'y' || inChar =='r' || inChar == 'R'){
  bool noreadfile;
  if (inChar =='r' || inChar == 'R'){ noreadfile = true; }else{ noreadfile = false; }
  
  root = SD.open("/");
  
  counter = 0;   
  Serial.println( freeMemory() );
  lastentryname01 = "";
 lastentryname0 = "";
 lastentryname1 = "";
 lastentryname2 = "";
 lastentryname3 = "";
 lastentryname4 = "";
 lastentryname5 = "";
 lastentryname6 = "";
 lastentryname7 = "";
 lastentryname8 = "";

  printDirectory(root, 0, noreadfile, -1);
  root.close();  
  Serial.print(F("done "));
  Serial.print( counter );
  Serial.println(F("!"));
  }  
}


void printDirectory( File dir, const int numTabs,  const bool noreadfile, int type) {

while(true) {
     
     
     File entry =  dir.openNextFile();
 
     char inCharx[0] = {}; inCharx[0] = Serial.read();
     if (inCharx[0] == 'X' || inCharx[0] == 'x'){
       break;  
     }
     if (! entry) {
       // no more files
       //Serial.println("**nomorefiles**");
       break;
     }
     //for (uint8_t i=0; i<numTabs; i++) {
     //  Serial.print('\t');
     //}
     //Serial.print(entry.name());
     //Serial.print("------");
     //Serial.print(numTabs);

     if (entry.isDirectory()) {
      
       String teststring = entry.name();
       
       if(numTabs==0 && teststring != lastentryname01){  lastentryname0=entry.name(); }
       if(numTabs+1==1 && teststring != lastentryname0){  lastentryname1=entry.name();}
       if(numTabs+1==2 && teststring != lastentryname1){  lastentryname2=entry.name();}
       if(numTabs+1==3 && teststring != lastentryname2){  lastentryname3=entry.name();}
       if(numTabs+1==4 && teststring != lastentryname3){  lastentryname4=entry.name();}
       if(numTabs+1==5 && teststring != lastentryname4){  lastentryname5=entry.name();}
       if(numTabs+1==6 && teststring != lastentryname5){  lastentryname6=entry.name();}
       if(numTabs+1==7 && teststring != lastentryname6){  lastentryname7=entry.name();}
       if(numTabs+1==8 && teststring != lastentryname7){  lastentryname8=entry.name();}
       
    
       printDirectory(entry, numTabs+1, noreadfile, 1);
      
     } else {
       if (type!=-1){ type = 0; }
      
       // files have sizes, directories do not
       //Serial.print("\t\t");
       //Serial.println(entry.size(), DEC);
     
      
       String thisentryname = "";
       
       if(numTabs==0 && type==-1){  thisentryname=entry.name();   thisentryname = "/" + thisentryname; }
       if(numTabs==0 && type==1){  thisentryname=entry.name();   thisentryname = "/" + lastentryname0 + "/" + thisentryname; }
       if(numTabs+1==1){  thisentryname=entry.name();   thisentryname = "/" + lastentryname0 + "/" + lastentryname1 + "/" + thisentryname; }
       if(numTabs+1==2){  thisentryname=entry.name();   thisentryname = "/" + lastentryname0 + "/" + lastentryname1 + "/" + lastentryname2 + "/" + thisentryname; }
       if(numTabs+1==3){  thisentryname=entry.name();   thisentryname = "/" + lastentryname0 + "/" + lastentryname1 + "/" + lastentryname2 + "/" + lastentryname3 + "/" + thisentryname; }
       if(numTabs+1==4){  thisentryname=entry.name();   thisentryname = "/" + lastentryname0 + "/" + lastentryname1 + "/" + lastentryname2 + "/" + lastentryname3 + "/" + lastentryname4 + "/" + thisentryname; }
       if(numTabs+1==5){  thisentryname=entry.name();   thisentryname = "/" + lastentryname0 + "/" + lastentryname1 + "/" + lastentryname2 + "/" + lastentryname3 + "/" + lastentryname4 + "/" + lastentryname5 + "/" + thisentryname; }
       if(numTabs+1==6){  thisentryname=entry.name();   thisentryname = "/" + lastentryname0 + "/" + lastentryname1 + "/" + lastentryname2 + "/" + lastentryname3 + "/" + lastentryname4 + "/" + lastentryname5 + "/" + lastentryname6 + "/" + thisentryname; }
       if(numTabs+1==7){  thisentryname=entry.name();   thisentryname = "/" + lastentryname0 + "/" + lastentryname1 + "/" + lastentryname2 + "/" + lastentryname3 + "/" + lastentryname4 + "/" + lastentryname5 + "/" + lastentryname6 + "/" + lastentryname7 + "/" + thisentryname; }
       if(numTabs+1==8){  thisentryname=entry.name();   thisentryname = "/" + lastentryname0 + "/" + lastentryname1 + "/" + lastentryname2 + "/" + lastentryname3 + "/" + lastentryname4 + "/" + lastentryname5 + "/" + lastentryname6 + "/" + lastentryname7 + "/" + lastentryname8 + "/" + thisentryname; }
//fix stuff
           thisentryname.replace("//","/");
           thisentryname.replace("//","/");
           thisentryname.replace("//","/"); // might have to have a short for loop for these replace method
if(type==-1){ thisentryname=entry.name(); thisentryname = "/" + thisentryname; }

             Serial.print( F("(") );
             Serial.print( thisentryname );
             Serial.println( F(")") );
 counter++;

   if(!noreadfile){   
      
       File dataFile = SD.open(thisentryname, FILE_READ ); 
 //     File dataFile = SD.open(entry.name());

  // if the file is available, read from it:
  if (dataFile) {
    while (dataFile.available()) {
      Serial.write(dataFile.read());
    }
    dataFile.close();
  }  
  // if the file isn't open, pop up an error:
  else {
    
    Serial.println(F("File error opening for reading..."));
  } 

   }//!noreadfile
       
     }
    if(entry){entry.close();} // = freezes at this line, 13 files listed, so test to see if entry object is still present before closing
    if (freeMemory() < 500){ Serial.print(F("Low memory ")); Serial.println( freeMemory() ); }
  }
//Serial.println(F("ending printdirectory"));
//Serial.println( freeMemory() );

}


#ifdef __arm__
// should use uinstd.h to define sbrk but Due causes a conflict
extern "C" char* sbrk(int incr);
#else  // __ARM__
extern char *__brkval;
#endif  // __arm__

int freeMemory() {
  char top;
#ifdef __arm__
  return &top - reinterpret_cast<char*>(sbrk(0));
#elif defined(CORE_TEENSY) || (ARDUINO > 103 && ARDUINO != 151)
  return &top - __brkval;
#else  // __arm__
  return __brkval ? &top - __brkval : &top - __malloc_heap_start;
#endif  // __arm__
}

char version is below, only runs on the MEGA 2560 r3; same as the above string version but has warnings. Also lists only 17 files ?!?

 /*
  SD card basic file example
 
 This example shows how to create and destroy an SD card file 	
 The circuit:
 * SD card attached to SPI bus as follows:
 ** MOSI - pin 11
 ** MISO - pin 12
 ** CLK - pin 13
 ** CS - pin 4
 
 created   Nov 2010
 by David A. Mellis
 modified 9 Apr 2012
 by Tom Igoe
 
 This example code is in the public domain.
 	 
 */

#include <SD.h>

File root;
static int counter;
char lastentryname01[1] = {0};
char lastentryname0[8] = {""};
char lastentryname1[8] = {""};
char lastentryname2[8] = {""};
char lastentryname3[8] = {""};
char lastentryname4[8] = {""};
char lastentryname5[8] = {""};
char lastentryname6[8] = {""};
char lastentryname7[8] = {""};
char lastentryname8[8] = {""};
char lastentryname9[8] = {""};
char lastentryname10[8] = {""};
char lastentryname11[8] = {""};
char lastentryname12[8] = {""};
char lastentryname13[8] = {""};
char lastentryname14[8] = {""};
char lastentryname15[8] = {""};
char lastentryname16[8] = {""};

void setup()
{
  // Open serial communications and wait for port to open:
#ifdef ARDUINO
if(ARDUINO <= 105){  //for IDE 1.0.5
  Serial.begin(115200); 
}else{  //latest stable version 1.8.19
  Serial.begin(2000000);
}
#elif
  Serial.begin(9600);
#endif

   while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }

Serial.println( freeMemory() );
Serial.print(F("Initializing SD card..."));
  // On the Ethernet Shield, CS is pin 4. It's set as an output by default.
  // Note that even if it's not used as the CS pin, the hardware SS pin 
  // (10 on most Arduino boards, 53 on the Mega) must be left as an output 
  // or the SD library functions will not work. 
  pinMode(SS, OUTPUT);

  if (!SD.begin(SS)) {
    Serial.println(F("initialization failed!"));
    return;
  }
  Serial.println(F("initialization done."));
  Serial.println(F("Send X to exit, Send R for readonly, Continue full read (Y/N)? "));
}

void loop()
{
  // nothing happens after setup finishes.
  char inChar = Serial.read();
  if (inChar == 'Y' || inChar == 'y' || inChar =='r' || inChar == 'R'){
  bool noreadfile;
  if (inChar =='r' || inChar == 'R'){ noreadfile = true; }else{ noreadfile = false; }
  
  root = SD.open("/");
  
  counter = 0;   
  Serial.println( freeMemory() );
  lastentryname01[0] = 0;
 lastentryname0[0] = lastentryname01[0];
 lastentryname1[0] = lastentryname01[0];
 lastentryname2[0] = lastentryname01[0];
 lastentryname3[0] = lastentryname01[0];
 lastentryname4[0] = lastentryname01[0];
 lastentryname5[0] = lastentryname01[0];
 lastentryname6[0] = lastentryname01[0];
 lastentryname7[0] = lastentryname01[0];
 lastentryname8[0] = lastentryname01[0];
 lastentryname9[0] = lastentryname01[0];
 lastentryname10[0] = lastentryname01[0];
 lastentryname11[0] = lastentryname01[0];
 lastentryname12[0] = lastentryname01[0];
 lastentryname13[0] = lastentryname01[0];
 lastentryname14[0] = lastentryname01[0];
 lastentryname15[0] = lastentryname01[0];
 lastentryname16[0] = lastentryname01[0];
 
  printDirectory(root, 0, noreadfile, -1);
  root.close();  
  Serial.print(F("done "));
  Serial.print( counter );
  Serial.println(F("!"));
  }  
}


void printDirectory( File dir, const int numTabs,  const bool noreadfile, int type) {

char bs[] = {"/"};
while(true) {
     
     
     File entry =  dir.openNextFile();
 
     char inCharx[0] = {}; inCharx[0] = Serial.read();
     if (inCharx[0] == 'X' || inCharx[0] == 'x'){
       break;  
     }
     if (! entry) {
       // no more files
       //Serial.println("**nomorefiles**");
       break;
     }
     //for (uint8_t i=0; i<numTabs; i++) {
     //  Serial.print('\t');
     //}
     //Serial.print(entry.name());
     //Serial.print("------");
     //Serial.print(numTabs);

     if (entry.isDirectory()) {
      
       if(numTabs==0){  strcpy(lastentryname0,entry.name()); }
       if(numTabs+1==1){  strcpy(lastentryname1,entry.name());}
       if(numTabs+1==2){  strcpy(lastentryname2,entry.name());}
       if(numTabs+1==3){  strcpy(lastentryname3,entry.name());}
       if(numTabs+1==4){  strcpy(lastentryname4,entry.name());}
       if(numTabs+1==5){  strcpy(lastentryname5,entry.name());}
       if(numTabs+1==6){  strcpy(lastentryname6,entry.name());}
       if(numTabs+1==7){  strcpy(lastentryname7,entry.name());}
       if(numTabs+1==8){  strcpy(lastentryname8,entry.name());}
       if(numTabs+1==9){  strcpy(lastentryname9,entry.name());}
       if(numTabs+1==10){  strcpy(lastentryname10,entry.name());}
       if(numTabs+1==11){  strcpy(lastentryname11,entry.name());}
       if(numTabs+1==12){  strcpy(lastentryname12,entry.name());}
       if(numTabs+1==13){  strcpy(lastentryname13,entry.name());}
       if(numTabs+1==14){  strcpy(lastentryname14,entry.name());}
       if(numTabs+1==15){  strcpy(lastentryname15,entry.name());}
       if(numTabs+1==16){  strcpy(lastentryname16,entry.name());}
    
       printDirectory(entry, numTabs+1, noreadfile, 1);
      
     } else {
       if (type!=-1){ type = 0; }
      
       // files have sizes, directories do not
       //Serial.print("\t\t");
       //Serial.println(entry.size(), DEC);
     
      
       char thisentryname[256] = {0};
       char entryname[8] = {0};
       
      // if(numTabs==0 && type==-1){  strcpy(entryname,entry.name());   strcpy(thisentryname, bs); strcat(thisentryname, entryname); }
      // if(numTabs==0 && type==1){  strcpy(entryname,entry.name());   strcpy(thisentryname, bs); strcat (thisentryname, lastentryname0); strcat(thisentryname,bs); strcat(thisentryname, entryname); }
       if(numTabs+1==1){  strcpy(entryname,entry.name());  strcpy(thisentryname, bs); strcat (thisentryname, lastentryname0); strcat(thisentryname,bs); strcat (thisentryname, lastentryname1); strcat(thisentryname,bs); strcat(thisentryname, entryname); }
       if(numTabs+1==2){  strcpy(entryname,entry.name());  strcpy(thisentryname, bs); strcat (thisentryname, lastentryname0); strcat(thisentryname,bs); strcat (thisentryname, lastentryname1); strcat(thisentryname,bs);  strcat (thisentryname, lastentryname2); strcat(thisentryname,bs); strcat(thisentryname, entryname); }
       if(numTabs+1==3){  strcpy(entryname,entry.name());  strcpy(thisentryname, bs); strcat (thisentryname, lastentryname0); strcat(thisentryname,bs); strcat (thisentryname, lastentryname1); strcat(thisentryname,bs);  strcat (thisentryname, lastentryname2); strcat(thisentryname,bs); strcat (thisentryname, lastentryname3); strcat(thisentryname,bs); strcat(thisentryname, entryname); }
       if(numTabs+1==4){  strcpy(entryname,entry.name());  strcpy(thisentryname, bs); strcat (thisentryname, lastentryname0); strcat(thisentryname,bs); strcat (thisentryname, lastentryname1); strcat(thisentryname,bs);  strcat (thisentryname, lastentryname2); strcat(thisentryname,bs); strcat (thisentryname, lastentryname3); strcat(thisentryname,bs); strcat (thisentryname, lastentryname4); strcat(thisentryname,bs); strcat(thisentryname, entryname); }

       if(numTabs+1==5){  strcpy(entryname,entry.name());  strcpy(thisentryname, bs); strcat (thisentryname, lastentryname0); strcat(thisentryname,bs); strcat (thisentryname, lastentryname1); strcat(thisentryname,bs);  strcat (thisentryname, lastentryname2); strcat(thisentryname,bs); strcat (thisentryname, lastentryname3); strcat(thisentryname,bs); strcat (thisentryname, lastentryname4); strcat(thisentryname,bs); strcat (thisentryname, lastentryname5); strcat(thisentryname,bs); strcat(thisentryname, entryname); }
       if(numTabs+1==6){  strcpy(entryname,entry.name());  strcpy(thisentryname, bs); strcat (thisentryname, lastentryname0); strcat(thisentryname,bs); strcat (thisentryname, lastentryname1); strcat(thisentryname,bs);  strcat (thisentryname, lastentryname2); strcat(thisentryname,bs); strcat (thisentryname, lastentryname3); strcat(thisentryname,bs); strcat (thisentryname, lastentryname4); strcat(thisentryname,bs); strcat (thisentryname, lastentryname5); strcat(thisentryname,bs); strcat (thisentryname, lastentryname6); strcat(thisentryname,bs); strcat(thisentryname, entryname); }
       if(numTabs+1==7){  strcpy(entryname,entry.name());  strcpy(thisentryname, bs); strcat (thisentryname, lastentryname0); strcat(thisentryname,bs); strcat (thisentryname, lastentryname1); strcat(thisentryname,bs);  strcat (thisentryname, lastentryname2); strcat(thisentryname,bs); strcat (thisentryname, lastentryname3); strcat(thisentryname,bs); strcat (thisentryname, lastentryname4); strcat(thisentryname,bs); strcat (thisentryname, lastentryname5); strcat(thisentryname,bs); strcat (thisentryname, lastentryname6); strcat(thisentryname,bs); strcat (thisentryname, lastentryname7); strcat(thisentryname,bs); strcat(thisentryname, entryname); }
       if(numTabs+1==8){  strcpy(entryname,entry.name());  strcpy(thisentryname, bs); strcat (thisentryname, lastentryname0); strcat(thisentryname,bs); strcat (thisentryname, lastentryname1); strcat(thisentryname,bs);  strcat (thisentryname, lastentryname2); strcat(thisentryname,bs); strcat (thisentryname, lastentryname3); strcat(thisentryname,bs); strcat (thisentryname, lastentryname4); strcat(thisentryname,bs); strcat (thisentryname, lastentryname5); strcat(thisentryname,bs); strcat (thisentryname, lastentryname6); strcat(thisentryname,bs); strcat (thisentryname, lastentryname7); strcat(thisentryname,bs); strcat (thisentryname, lastentryname8); strcat(thisentryname,bs); strcat(thisentryname, entryname); }

//fix stuff
  //         thisentryname.replace("//","/");
  //         thisentryname.replace("//","/");
  //         thisentryname.replace("//","/"); // might have to have a short for loop for these replace method

  
if(type==-1){ strcpy(thisentryname, bs); strcat(thisentryname, entryname); }

             Serial.print( F("(") );
             //Serial.write( thisentryname );

             
             //try removing multiple / symbols
             char lastchar[8] = {0};
             bool flag = false;
             
             int sx = 0; while(sx<int(strlen(thisentryname))){ 

              char mygetchar[1] = {thisentryname[sx]}; // = {0};

              strcpy(mygetchar[0],thisentryname[sx]);
              
              if(memcmp(mygetchar,bs,1)!=0 && memcmp(lastchar,bs,1)!=0){
              
                 Serial.write(thisentryname[sx]);  
                 
                    }else{ 
                      
                       if(flag==true){Serial.write(bs[0]);flag=false;}else{flag=true; }
                 
                 strcpy(lastchar[0],thisentryname[sx]); 
                 
                 }
              
              sx++;
              
              }
             
             Serial.println( F(")") );
 counter++;

   if(!noreadfile){   
      
       File dataFile = SD.open(String(thisentryname).c_str(), FILE_READ ); 
 //     File dataFile = SD.open(entry.name());

  // if the file is available, read from it:
  if (dataFile) {
    while (dataFile.available()) {
      Serial.write(dataFile.read());
    }
    dataFile.close();
  }  
  // if the file isn't open, pop up an error:
  else {
    
    Serial.println(F("File error opening for reading..."));
  } 

   }//!noreadfile
       
     }
    if(entry){entry.close();} // = freezes at this line, 13 files listed, so test to see if entry object is still present before closing
    if (freeMemory() < 500){ Serial.print(F("Low memory ")); Serial.println( freeMemory() ); }
  }
//Serial.println(F("ending printdirectory"));
//Serial.println( freeMemory() );

}


#ifdef __arm__
// should use uinstd.h to define sbrk but Due causes a conflict
extern "C" char* sbrk(int incr);
#else  // __ARM__
extern char *__brkval;
#endif  // __arm__

int freeMemory() {
  char top;
#ifdef __arm__
  return &top - reinterpret_cast<char*>(sbrk(0));
#elif defined(CORE_TEENSY) || (ARDUINO > 103 && ARDUINO != 151)
  return &top - __brkval;
#else  // __arm__
  return __brkval ? &top - __brkval : &top - __malloc_heap_start;
#endif  // __arm__
}

SD card is DOS 8.3 FAT table. Root directory is limited to 256 entries, subdirectories are unlimited. SD card driver pukes if asked to create a filename longer than 8.3

Got the following code to work on a UNO; And on MEGA with a revision to do more folder depth.

Found out that the SD Card had become corrupted resulting in a listing of 17 files, now getting 474 files listed on Mega (some issues).

 /*
  SD card basic file example
 
 This example shows how to create and destroy an SD card file 	
 The circuit:
 * SD card attached to SPI bus as follows:
 ** MOSI - pin 11
 ** MISO - pin 12
 ** CLK - pin 13
 ** CS - pin 4
 
 created   Nov 2010
 by David A. Mellis
 modified 9 Apr 2012
 by Tom Igoe
 
 This example code is in the public domain.
 	 
 */

#include <SD.h>

//#define MEGA 1; //uncomment on MEGA boards



File root;

static int counter;
char thisentryname[256] = {0};
const char lastentryname01[1] = {0};
char lastentryname0[8] = {""};
char lastentryname1[8] = {""};
char lastentryname2[8] = {""};
char lastentryname3[8] = {""};
char lastentryname4[8] = {""};
char lastentryname5[8] = {""};
char lastentryname6[8] = {""};
char lastentryname7[8] = {""};
char lastentryname8[8] = {""};
#ifdef MEGA
char lastentryname9[8] = {""};
char lastentryname10[8] = {""};
char lastentryname11[8] = {""};
char lastentryname12[8] = {""};
char lastentryname13[8] = {""};
char lastentryname14[8] = {""};
char lastentryname15[8] = {""};
char lastentryname16[8] = {""};
#endif

void setup()
{
  // Open serial communications and wait for port to open:
#ifdef ARDUINO
if(ARDUINO <= 105){  //for IDE 1.0.5
  Serial.begin(115200); 
}else{  //latest stable version 1.8.19
  Serial.begin(2000000);
}
#elif
  Serial.begin(9600);
#endif

   while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }

Serial.println( freeMemory() );
Serial.print(F("Initializing SD card..."));
  // On the Ethernet Shield, CS is pin 4. It's set as an output by default.
  // Note that even if it's not used as the CS pin, the hardware SS pin 
  // (10 on most Arduino boards, 53 on the Mega) must be left as an output 
  // or the SD library functions will not work. 
  pinMode(SS, OUTPUT);

  if (!SD.begin(SS)) {
    Serial.println(F("initialization failed!"));
    return;
  }
  Serial.println(F("initialization done."));
  Serial.println(F("Send X to exit, Send R for readonly, Continue full read (Y/N)? "));
}

void loop()
{
  // nothing happens after setup finishes.
  char inChar = Serial.read();
  if (inChar == 'Y' || inChar == 'y' || inChar =='r' || inChar == 'R'){
  bool noreadfile;
  if (inChar =='r' || inChar == 'R'){ noreadfile = true; }else{ noreadfile = false; }
  
  root = SD.open("/");
  
  counter = 0;   
  Serial.println( freeMemory() );
  //lastentryname01[0] = 0;
 lastentryname0[0] = lastentryname01[0];
 lastentryname1[0] = lastentryname01[0];
 lastentryname2[0] = lastentryname01[0];
 lastentryname3[0] = lastentryname01[0];
 lastentryname4[0] = lastentryname01[0];
 lastentryname5[0] = lastentryname01[0];
 lastentryname6[0] = lastentryname01[0];
 lastentryname7[0] = lastentryname01[0];
 lastentryname8[0] = lastentryname01[0];
#ifdef MEGA
  lastentryname9[0] = lastentryname01[0];
 lastentryname10[0] = lastentryname01[0];
 lastentryname11[0] = lastentryname01[0];
 lastentryname12[0] = lastentryname01[0];
 lastentryname13[0] = lastentryname01[0];
 lastentryname14[0] = lastentryname01[0];
 lastentryname15[0] = lastentryname01[0];
 lastentryname16[0] = lastentryname01[0];
#endif
  printDirectory(root, 0, noreadfile, -1);
  root.close();  
  Serial.print(F("done "));
  Serial.print( counter );
  Serial.println(F("!"));
  }  
}


void printDirectory( File dir, const int numTabs,  const bool noreadfile, int type) {

const char bs[] = {"/"};
    
while(true) {
     
     File entry = dir.openNextFile();
     
     char inCharx[0] = {}; inCharx[0] = Serial.read();
     if (inCharx[0] == 'X' || inCharx[0] == 'x'){
       break;  
     }
     if (! entry) {
       // no more files
       //Serial.println("**nomorefiles**");
       break;
     }
     //for (uint8_t i=0; i<numTabs; i++) {
     //  Serial.print('\t');
     //}
     //Serial.print(entry.name());
     //Serial.print("------");
     //Serial.print(numTabs);

     if (entry.isDirectory()) {
      
       if(numTabs==0){  strcpy(lastentryname0,entry.name()); }
       if(numTabs+1==1){  strcpy(lastentryname1,entry.name());}
       if(numTabs+1==2){  strcpy(lastentryname2,entry.name());}
       if(numTabs+1==3){  strcpy(lastentryname3,entry.name());}
       if(numTabs+1==4){  strcpy(lastentryname4,entry.name());}
       if(numTabs+1==5){  strcpy(lastentryname5,entry.name());}
       if(numTabs+1==6){  strcpy(lastentryname6,entry.name());}
       if(numTabs+1==7){  strcpy(lastentryname7,entry.name());}
       if(numTabs+1==8){  strcpy(lastentryname8,entry.name());}
#ifdef MEGA
       if(numTabs+1==9){  strcpy(lastentryname9,entry.name());}
       if(numTabs+1==10){  strcpy(lastentryname10,entry.name());}
       if(numTabs+1==11){  strcpy(lastentryname11,entry.name());}
       if(numTabs+1==12){  strcpy(lastentryname12,entry.name());}
       if(numTabs+1==13){  strcpy(lastentryname13,entry.name());}
       if(numTabs+1==14){  strcpy(lastentryname14,entry.name());}
       if(numTabs+1==15){  strcpy(lastentryname15,entry.name());}
       if(numTabs+1==16){  strcpy(lastentryname16,entry.name());}
#endif    
      printDirectory(entry, numTabs+1, noreadfile, 1); 
      
      
     } else {
       if (type!=-1){ type = 0; }
      
       // files have sizes, directories do not
       //Serial.print("\t\t");
       //Serial.println(entry.size(), DEC);
     
      
//       char thisentryname[256] = {0};
       char entryname[int(String(entry.name()).length())] = {0};
       
      // if(numTabs==0 && type==-1){  strcpy(entryname,entry.name());   strcpy(thisentryname, bs); strcat(thisentryname, entryname); }
      // if(numTabs==0 && type==1){  strcpy(entryname,entry.name());   strcpy(thisentryname, bs); strcat (thisentryname, lastentryname0); strcat(thisentryname,bs); strcat(thisentryname, entryname); }
       if(numTabs+1==1){  strcpy(entryname,entry.name());  strcpy(thisentryname, bs); strcat (thisentryname, lastentryname0); strcat(thisentryname,bs); strcat (thisentryname, lastentryname1); strcat(thisentryname,bs); strcat(thisentryname, entryname); }
       if(numTabs+1==2){  strcpy(entryname,entry.name());  strcpy(thisentryname, bs); strcat (thisentryname, lastentryname0); strcat(thisentryname,bs); strcat (thisentryname, lastentryname1); strcat(thisentryname,bs);  strcat (thisentryname, lastentryname2); strcat(thisentryname,bs); strcat(thisentryname, entryname); }
       if(numTabs+1==3){  strcpy(entryname,entry.name());  strcpy(thisentryname, bs); strcat (thisentryname, lastentryname0); strcat(thisentryname,bs); strcat (thisentryname, lastentryname1); strcat(thisentryname,bs);  strcat (thisentryname, lastentryname2); strcat(thisentryname,bs); strcat (thisentryname, lastentryname3); strcat(thisentryname,bs); strcat(thisentryname, entryname); }
       if(numTabs+1==4){  strcpy(entryname,entry.name());  strcpy(thisentryname, bs); strcat (thisentryname, lastentryname0); strcat(thisentryname,bs); strcat (thisentryname, lastentryname1); strcat(thisentryname,bs);  strcat (thisentryname, lastentryname2); strcat(thisentryname,bs); strcat (thisentryname, lastentryname3); strcat(thisentryname,bs); strcat (thisentryname, lastentryname4); strcat(thisentryname,bs); strcat(thisentryname, entryname); }

       if(numTabs+1==5){  strcpy(entryname,entry.name());  strcpy(thisentryname, bs); strcat (thisentryname, lastentryname0); strcat(thisentryname,bs); strcat (thisentryname, lastentryname1); strcat(thisentryname,bs);  strcat (thisentryname, lastentryname2); strcat(thisentryname,bs); strcat (thisentryname, lastentryname3); strcat(thisentryname,bs); strcat (thisentryname, lastentryname4); strcat(thisentryname,bs); strcat (thisentryname, lastentryname5); strcat(thisentryname,bs); strcat(thisentryname, entryname); }
       if(numTabs+1==6){  strcpy(entryname,entry.name());  strcpy(thisentryname, bs); strcat (thisentryname, lastentryname0); strcat(thisentryname,bs); strcat (thisentryname, lastentryname1); strcat(thisentryname,bs);  strcat (thisentryname, lastentryname2); strcat(thisentryname,bs); strcat (thisentryname, lastentryname3); strcat(thisentryname,bs); strcat (thisentryname, lastentryname4); strcat(thisentryname,bs); strcat (thisentryname, lastentryname5); strcat(thisentryname,bs); strcat (thisentryname, lastentryname6); strcat(thisentryname,bs); strcat(thisentryname, entryname); }
       if(numTabs+1==7){  strcpy(entryname,entry.name());  strcpy(thisentryname, bs); strcat (thisentryname, lastentryname0); strcat(thisentryname,bs); strcat (thisentryname, lastentryname1); strcat(thisentryname,bs);  strcat (thisentryname, lastentryname2); strcat(thisentryname,bs); strcat (thisentryname, lastentryname3); strcat(thisentryname,bs); strcat (thisentryname, lastentryname4); strcat(thisentryname,bs); strcat (thisentryname, lastentryname5); strcat(thisentryname,bs); strcat (thisentryname, lastentryname6); strcat(thisentryname,bs); strcat (thisentryname, lastentryname7); strcat(thisentryname,bs); strcat(thisentryname, entryname); }
       if(numTabs+1==8){  strcpy(entryname,entry.name());  strcpy(thisentryname, bs); strcat (thisentryname, lastentryname0); strcat(thisentryname,bs); strcat (thisentryname, lastentryname1); strcat(thisentryname,bs);  strcat (thisentryname, lastentryname2); strcat(thisentryname,bs); strcat (thisentryname, lastentryname3); strcat(thisentryname,bs); strcat (thisentryname, lastentryname4); strcat(thisentryname,bs); strcat (thisentryname, lastentryname5); strcat(thisentryname,bs); strcat (thisentryname, lastentryname6); strcat(thisentryname,bs); strcat (thisentryname, lastentryname7); strcat(thisentryname,bs); strcat (thisentryname, lastentryname8); strcat(thisentryname,bs); strcat(thisentryname, entryname); }

#ifdef MEGA
       if(numTabs+1==9){  strcpy(entryname,entry.name());  strcpy(thisentryname, bs); strcat (thisentryname, lastentryname0); strcat(thisentryname,bs); strcat (thisentryname, lastentryname1); strcat(thisentryname,bs);  strcat (thisentryname, lastentryname2); strcat(thisentryname,bs); strcat (thisentryname, lastentryname3); strcat(thisentryname,bs); strcat (thisentryname, lastentryname4); strcat(thisentryname,bs); strcat (thisentryname, lastentryname5); strcat(thisentryname,bs); strcat (thisentryname, lastentryname6); strcat(thisentryname,bs); strcat (thisentryname, lastentryname7); strcat(thisentryname,bs); strcat (thisentryname, lastentryname8); strcat(thisentryname,bs); strcat(thisentryname,lastentryname9); strcat(thisentryname,bs); strcat(thisentryname, entryname); }
       if(numTabs+1==10){ strcpy(entryname,entry.name());  strcpy(thisentryname, bs); strcat (thisentryname, lastentryname0); strcat(thisentryname,bs); strcat (thisentryname, lastentryname1); strcat(thisentryname,bs);  strcat (thisentryname, lastentryname2); strcat(thisentryname,bs); strcat (thisentryname, lastentryname3); strcat(thisentryname,bs); strcat (thisentryname, lastentryname4); strcat(thisentryname,bs); strcat (thisentryname, lastentryname5); strcat(thisentryname,bs); strcat (thisentryname, lastentryname6); strcat(thisentryname,bs); strcat (thisentryname, lastentryname7); strcat(thisentryname,bs); strcat (thisentryname, lastentryname8); strcat(thisentryname,bs); strcat(thisentryname,lastentryname9); strcat(thisentryname,bs); strcat(thisentryname,lastentryname10); strcat(thisentryname,bs); strcat(thisentryname, entryname); }
       if(numTabs+1==11){ strcpy(entryname,entry.name());  strcpy(thisentryname, bs); strcat (thisentryname, lastentryname0); strcat(thisentryname,bs); strcat (thisentryname, lastentryname1); strcat(thisentryname,bs);  strcat (thisentryname, lastentryname2); strcat(thisentryname,bs); strcat (thisentryname, lastentryname3); strcat(thisentryname,bs); strcat (thisentryname, lastentryname4); strcat(thisentryname,bs); strcat (thisentryname, lastentryname5); strcat(thisentryname,bs); strcat (thisentryname, lastentryname6); strcat(thisentryname,bs); strcat (thisentryname, lastentryname7); strcat(thisentryname,bs); strcat (thisentryname, lastentryname8); strcat(thisentryname,bs); strcat(thisentryname,lastentryname9); strcat(thisentryname,bs); strcat(thisentryname,lastentryname10); strcat(thisentryname,bs); strcat(thisentryname,lastentryname11); strcat(thisentryname,bs); strcat(thisentryname, entryname); }
       if(numTabs+1==12){ strcpy(entryname,entry.name());  strcpy(thisentryname, bs); strcat (thisentryname, lastentryname0); strcat(thisentryname,bs); strcat (thisentryname, lastentryname1); strcat(thisentryname,bs);  strcat (thisentryname, lastentryname2); strcat(thisentryname,bs); strcat (thisentryname, lastentryname3); strcat(thisentryname,bs); strcat (thisentryname, lastentryname4); strcat(thisentryname,bs); strcat (thisentryname, lastentryname5); strcat(thisentryname,bs); strcat (thisentryname, lastentryname6); strcat(thisentryname,bs); strcat (thisentryname, lastentryname7); strcat(thisentryname,bs); strcat (thisentryname, lastentryname8); strcat(thisentryname,bs); strcat(thisentryname,lastentryname9); strcat(thisentryname,bs); strcat(thisentryname,lastentryname10); strcat(thisentryname,bs); strcat(thisentryname,lastentryname11); strcat(thisentryname,bs); strcat(thisentryname,lastentryname12); strcat(thisentryname,bs); strcat(thisentryname, entryname); }

       if(numTabs+1==13){ strcpy(entryname,entry.name());  strcpy(thisentryname, bs); strcat (thisentryname, lastentryname0); strcat(thisentryname,bs); strcat (thisentryname, lastentryname1); strcat(thisentryname,bs);  strcat (thisentryname, lastentryname2); strcat(thisentryname,bs); strcat (thisentryname, lastentryname3); strcat(thisentryname,bs); strcat (thisentryname, lastentryname4); strcat(thisentryname,bs); strcat (thisentryname, lastentryname5); strcat(thisentryname,bs); strcat (thisentryname, lastentryname6); strcat(thisentryname,bs); strcat (thisentryname, lastentryname7); strcat(thisentryname,bs); strcat (thisentryname, lastentryname8); strcat(thisentryname,bs); strcat(thisentryname,lastentryname9); strcat(thisentryname,bs); strcat(thisentryname,lastentryname10); strcat(thisentryname,bs); strcat(thisentryname,lastentryname11); strcat(thisentryname,bs); strcat(thisentryname,lastentryname12); strcat(thisentryname,bs); strcat(thisentryname,lastentryname13); strcat(thisentryname,bs); strcat(thisentryname, entryname); }
       if(numTabs+1==14){ strcpy(entryname,entry.name());  strcpy(thisentryname, bs); strcat (thisentryname, lastentryname0); strcat(thisentryname,bs); strcat (thisentryname, lastentryname1); strcat(thisentryname,bs);  strcat (thisentryname, lastentryname2); strcat(thisentryname,bs); strcat (thisentryname, lastentryname3); strcat(thisentryname,bs); strcat (thisentryname, lastentryname4); strcat(thisentryname,bs); strcat (thisentryname, lastentryname5); strcat(thisentryname,bs); strcat (thisentryname, lastentryname6); strcat(thisentryname,bs); strcat (thisentryname, lastentryname7); strcat(thisentryname,bs); strcat (thisentryname, lastentryname8); strcat(thisentryname,bs); strcat(thisentryname,lastentryname9); strcat(thisentryname,bs); strcat(thisentryname,lastentryname10); strcat(thisentryname,bs); strcat(thisentryname,lastentryname11); strcat(thisentryname,bs); strcat(thisentryname,lastentryname12); strcat(thisentryname,bs); strcat(thisentryname,lastentryname13); strcat(thisentryname,bs); strcat(thisentryname,lastentryname14); strcat(thisentryname,bs); strcat(thisentryname, entryname); }
       if(numTabs+1==15){ strcpy(entryname,entry.name());  strcpy(thisentryname, bs); strcat (thisentryname, lastentryname0); strcat(thisentryname,bs); strcat (thisentryname, lastentryname1); strcat(thisentryname,bs);  strcat (thisentryname, lastentryname2); strcat(thisentryname,bs); strcat (thisentryname, lastentryname3); strcat(thisentryname,bs); strcat (thisentryname, lastentryname4); strcat(thisentryname,bs); strcat (thisentryname, lastentryname5); strcat(thisentryname,bs); strcat (thisentryname, lastentryname6); strcat(thisentryname,bs); strcat (thisentryname, lastentryname7); strcat(thisentryname,bs); strcat (thisentryname, lastentryname8); strcat(thisentryname,bs); strcat(thisentryname,lastentryname9); strcat(thisentryname,bs); strcat(thisentryname,lastentryname10); strcat(thisentryname,bs); strcat(thisentryname,lastentryname11); strcat(thisentryname,bs); strcat(thisentryname,lastentryname12); strcat(thisentryname,bs); strcat(thisentryname,lastentryname13); strcat(thisentryname,bs); strcat(thisentryname,lastentryname14); strcat(thisentryname,bs); strcat(thisentryname,lastentryname15); strcat(thisentryname,bs); strcat(thisentryname, entryname); }
       if(numTabs+1==16){ strcpy(entryname,entry.name());  strcpy(thisentryname, bs); strcat (thisentryname, lastentryname0); strcat(thisentryname,bs); strcat (thisentryname, lastentryname1); strcat(thisentryname,bs);  strcat (thisentryname, lastentryname2); strcat(thisentryname,bs); strcat (thisentryname, lastentryname3); strcat(thisentryname,bs); strcat (thisentryname, lastentryname4); strcat(thisentryname,bs); strcat (thisentryname, lastentryname5); strcat(thisentryname,bs); strcat (thisentryname, lastentryname6); strcat(thisentryname,bs); strcat (thisentryname, lastentryname7); strcat(thisentryname,bs); strcat (thisentryname, lastentryname8); strcat(thisentryname,bs); strcat(thisentryname,lastentryname9); strcat(thisentryname,bs); strcat(thisentryname,lastentryname10); strcat(thisentryname,bs); strcat(thisentryname,lastentryname11); strcat(thisentryname,bs); strcat(thisentryname,lastentryname12); strcat(thisentryname,bs); strcat(thisentryname,lastentryname13); strcat(thisentryname,bs); strcat(thisentryname,lastentryname14); strcat(thisentryname,bs); strcat(thisentryname,lastentryname15); strcat(thisentryname,bs); strcat(thisentryname,lastentryname16); strcat(thisentryname,bs); strcat(thisentryname, entryname); }
#endif

if(type==-1){ strcpy(thisentryname, bs); strcat(thisentryname, entryname); }

             Serial.print( F("(") );
             //Serial.write( thisentryname );

             
             //try removing multiple / symbols
  //           char lastchar[8] = {0};
    //         bool flag = false;

String charbuild =F("");

charbuild.reserve(int(strlen(thisentryname)));

charbuild = thisentryname;
//while( charbuild.indexOf("//")!=-1 ){ charbuild.replace("//","/"); }

charbuild.replace(F("//"),F("/"));
charbuild.replace(F("//"),F("/"));
charbuild.replace(F("//"),F("/"));
charbuild.replace(F("//"),F("/"));
charbuild.replace(F("//"),F("/"));
charbuild.replace(F("//"),F("/"));
charbuild.replace(F("//"),F("/"));
charbuild.replace(F("//"),F("/"));
#ifdef MEGA
charbuild.replace(F("//"),F("/"));
charbuild.replace(F("//"),F("/"));
charbuild.replace(F("//"),F("/"));
charbuild.replace(F("//"),F("/"));
charbuild.replace(F("//"),F("/"));
charbuild.replace(F("//"),F("/"));
charbuild.replace(F("//"),F("/"));
charbuild.replace(F("//"),F("/"));
#endif

/*String dlastchar = ""; dlastchar.reserve(1);
for (char *p = thisentryname; *p; p++) {
  if(*p == '/'){ if(dlastchar.indexOf('/')==-1){Serial.print("hi");dlastchar = *p;}else{dlastchar = *p;}}
   if(dlastchar.indexOf('/')==-1){charbuild += *p;  }else{ if(*p==bs[0]){charbuild += dlastchar; p++;}else{p++;}
   dlastchar=*p; 
   }
  }
*/

strcpy(thisentryname,charbuild.c_str());

             
             int sx = 0; while(sx<int(strlen(thisentryname))){ 
                 Serial.write(thisentryname[sx]);  
              sx++;
              }
             
             Serial.println( F(")") );
 counter++;

   if(!noreadfile){   
      
       File dataFile = SD.open(String(thisentryname).c_str(), FILE_READ ); 
 //     File dataFile = SD.open(entry.name());

  // if the file is available, read from it:
  if (dataFile) {
    while (dataFile.available()) {
      Serial.write(dataFile.read());
    }
    dataFile.close();
  }  
  // if the file isn't open, pop up an error:
  else {
    
    Serial.println(F("File error opening for reading..."));
  } 

   }//!noreadfile
      // free(thisentryname);
     }
    
    if(entry/*.isDirectory()*/){entry.close();} // = freezes at this line, 13 files listed, so test to see if entry object is still present before closing
    if (freeMemory() < 500){ Serial.print(F("Low memory ")); Serial.println( freeMemory() ); }
  }
//Serial.println(F("ending printdirectory"));
//Serial.println( freeMemory() );
//if(dir.isDirectory()){dir.close();}

}


#ifdef __arm__
// should use uinstd.h to define sbrk but Due causes a conflict
extern "C" char* sbrk(int incr);
#else  // __ARM__
extern char *__brkval;
#endif  // __arm__

int freeMemory() {
  char top;
#ifdef __arm__
  return &top - reinterpret_cast<char*>(sbrk(0));
#elif defined(CORE_TEENSY) || (ARDUINO > 103 && ARDUINO != 151)
  return &top - __brkval;
#else  // __arm__
  return __brkval ? &top - __brkval : &top - __malloc_heap_start;
#endif  // __arm__
}

I do not have time at the moment to work on the code, but a few observations:

char thisentryname[256] = {0};
const char lastentryname01[1]  = {0};
char lastentryname0[8] = {""};
char lastentryname1[8] = {""};
char lastentryname2[8] = {""};
char lastentryname3[8] = {""};
char lastentryname4[8] = {""};
char lastentryname5[8] = {""};
char lastentryname6[8] = {""};
char lastentryname7[8] = {""};
char lastentryname8[8] = {""};
#ifdef MEGA
char lastentryname9[8] = {""};
char lastentryname10[8] = {""};
char lastentryname11[8] = {""};
char lastentryname12[8] = {""};
char lastentryname13[8] = {""};
char lastentryname14[8] = {""};
char lastentryname15[8] = {""};
char lastentryname16[8] = {""};
#endif

As others have said numerous times, if you start having to number variables, use an array. This will also greatly simplify my next suggestion. I have not checked the actual code, but are 8 char enough to hold the name? I know the SD card uses 8.3 filename format, but an 8-character name would seemingly need at least 9 characters.

      if (numTabs + 1 == 1) {
        strcpy(entryname, entry.name());
        strcpy(thisentryname, bs);
        strcat (thisentryname, lastentryname0);
        strcat(thisentryname, bs);
        strcat (thisentryname, lastentryname1);
        strcat(thisentryname, bs);
        strcat(thisentryname, entryname);
      }
      if (numTabs + 1 == 2) {
        strcpy(entryname, entry.name());
        strcpy(thisentryname, bs);
        strcat (thisentryname, lastentryname0);
        strcat(thisentryname, bs);
        strcat (thisentryname, lastentryname1);
        strcat(thisentryname, bs);
        strcat (thisentryname, lastentryname2);
        strcat(thisentryname, bs);
        strcat(thisentryname, entryname);
      }
      if (numTabs + 1 == 3) {
        strcpy(entryname, entry.name());
        strcpy(thisentryname, bs);
        strcat (thisentryname, lastentryname0);
        strcat(thisentryname, bs);
        strcat (thisentryname, lastentryname1);
        strcat(thisentryname, bs);
        strcat (thisentryname, lastentryname2);
        strcat(thisentryname, bs);
        strcat (thisentryname, lastentryname3);
        strcat(thisentryname, bs);
        strcat(thisentryname, entryname);
      }
      if (numTabs + 1 == 4) {
        strcpy(entryname, entry.name());
        strcpy(thisentryname, bs);
        strcat (thisentryname, lastentryname0);
        strcat(thisentryname, bs);
        strcat (thisentryname, lastentryname1);
        strcat(thisentryname, bs);
        strcat (thisentryname, lastentryname2);
        strcat(thisentryname, bs);
        strcat (thisentryname, lastentryname3);
        strcat(thisentryname, bs);
        strcat (thisentryname, lastentryname4);
        strcat(thisentryname, bs);
        strcat(thisentryname, entryname);
      }

Too much redundant code, much easier using an array and concatenating the array elements based on numTabs.


      String charbuild = F("");

      charbuild.reserve(int(strlen(thisentryname)));

      charbuild = thisentryname;
      //while( charbuild.indexOf("//")!=-1 ){ charbuild.replace("//","/"); }

      charbuild.replace(F("//"), F("/"));
      charbuild.replace(F("//"), F("/"));
      charbuild.replace(F("//"), F("/"));
      charbuild.replace(F("//"), F("/"));
      charbuild.replace(F("//"), F("/"));
      charbuild.replace(F("//"), F("/"));
      charbuild.replace(F("//"), F("/"));
      charbuild.replace(F("//"), F("/"));
#ifdef MEGA
      charbuild.replace(F("//"), F("/"));
      charbuild.replace(F("//"), F("/"));
      charbuild.replace(F("//"), F("/"));
      charbuild.replace(F("//"), F("/"));
      charbuild.replace(F("//"), F("/"));
      charbuild.replace(F("//"), F("/"));
      charbuild.replace(F("//"), F("/"));
      charbuild.replace(F("//"), F("/"));
#endif

      /*String dlastchar = ""; dlastchar.reserve(1);
        for (char *p = thisentryname; *p; p++) {
        if(*p == '/'){ if(dlastchar.indexOf('/')==-1){Serial.print("hi");dlastchar = *p;}else{dlastchar = *p;}}
         if(dlastchar.indexOf('/')==-1){charbuild += *p;  }else{ if(*p==bs[0]){charbuild += dlastchar; p++;}else{p++;}
         dlastchar=*p;
         }
        }
      */

      strcpy(thisentryname, charbuild.c_str());

Forget the String manipulation, do the manipulation with the string (and preferably do the conversion from "//" to "/" while building the string from the individual parts.

Didnt have the time to play with arrays but I will make some time...

There are major issues with the output.

Found the reason for the "//" issue with the code; it seems that the printDirectory numTabs isn't correctly referencing the actual directory levels.

That may be related to the char arrays for the various lastentryname being too small to hold an eight-character directory name (there is no space for the terminating null).

You can save a bit of memory by making the thisentryname char array smaller. The maximum directory name will be eight characters, and the maximum file name twelve characters, so you should be able to calculate the maximum size of thisentryname based on the maximum number of directory levels you allocated storage for.