greiman / SdFat

Arduino FAT16/FAT32 exFAT Library
MIT License
1.07k stars 502 forks source link

Can't delete files and folder #374

Closed FernandoGarcia closed 2 years ago

FernandoGarcia commented 2 years ago

Hi!

Sorry by bother you here with a question but I can't find an answer.

Could you tell me please why I can't delete the folder "veiculos" and the files inside using this code?

#include <SdFat.h>

SdFat SD;
File file;
File root;

String folder = "veiculos";

#define LOG(...) Serial.print(__VA_ARGS__)
#define LOGLN(...) Serial.println(__VA_ARGS__)

void setup() {
  SD.begin (SPI_QUARTER_SPEED, 53);
  Serial.begin(115200);

  char currentFile[15];

  if (!root.open(folder.c_str()))
  {
    LOG(F("Can't open the folder "));
    LOGLN(folder);
  }
  else
  {
    LOG(F("The folder "));
    LOG(folder);
    LOGLN(F(" is open"));
  }

  while (file.openNext(&root, O_RDONLY))
  {
    file.getName(currentFile, 15);
    file.close();

    if (file.isOpen())
    {
      LOGLN(F("The file is open"));
    }
    else
    {
      LOGLN(F("The file is closed"));
    }

    if (file.remove(currentFile))
    {
      LOG(currentFile);
      LOGLN(F(" was deleted"));
    }
    else
    {
      LOG(currentFile);
      LOGLN(F(" wasn't deleted"));
    }
  }

  SD.chdir("/");

  SD.ls();

  if (SD.rmdir(folder))
  {
    LOG(F("The folder "));
    LOG(folder);
    LOGLN(F(" was deleted."));
  }
  else
  {
    LOG(F("The folder "));
    LOG(folder);
    LOGLN(F(" wasn't deleted"));
  }

}

void loop() {}

The output for this code is:

The folder veiculos is open
The file is closed
175628d2.txt wasn't deleted

The file is closed
20fb6e1b.txt wasn't deleted

The file is closed
ff28f40a.txt wasn't deleted

The file is closed
fe29f30b.txt wasn't deleted

The file is closed
fd2af20c.txt wasn't deleted

The file is closed
fc2bf10d.txt wasn't deleted

The file is closed
fb2cf00e.txt wasn't deleted

The file is closed
70dfe427.txt wasn't deleted

The file is closed
e77e23d2.txt wasn't deleted

The file is closed
7038d102.txt wasn't deleted

The file is closed
411f7527.txt wasn't deleted

imagens/
veiculos/
usuarios/
envios/
The folder veiculos wasn't deleted

Thanks in advance! Best regards.

greiman commented 2 years ago

if (file.remove(currentFile)) won't work unless you have the full path.

for example: "veiculos/175628d2.txt"

FernandoGarcia commented 2 years ago

The files used were created in this way:

  if(!SD.exists(folder))
  {
    if (!SD.mkdir(folder))
    {
      LOG(F("Can't create the folder "));
      LOGLN(folder);
      return;
    }
    else
    {
      LOG(F("The folder "));
      LOG(folder);
      LOGLN(F(" was created"));
    }
  }
    file = SD.open(fileName, FILE_WRITE);

    if (!file)
    {
      LOG(F("Can't create "));
      LOGLN(fileName);
      return;
    }

    String data = "{\"nome\":\"";
    data += Json["adi"][i]["nome"].as<String>();
    data += "\",\"tag\":";
    data += Json["adi"][i]["tag"].as<String>();
    data += "}";

    file.println(data);

    file.close();
FernandoGarcia commented 2 years ago

if (file.remove(currentFile)) won't work unless you have the full path.

for example: "veiculos/175628d2.txt"

Thanks for your answer!

Even if the current directory is "veiculos"?

Why SD.rmdir(folder) can't remove the folder and files?

For what I can see here it could make the job but doesn't.

bool rmdir();
  /** Recursively delete a directory and all contained files.
   *
   * This is like the Unix/Linux 'rm -rf *' if called with the root directory
   * hence the name.
   *
   * Warning - This will remove all contents of the directory including
   * subdirectories.  The directory will then be removed if it is not root.
   * The read-only attribute for files will be ignored.
   *
   * \note This function should not be used to delete the 8.3 version of
   * a directory that has a long name.  See remove() and rmdir().
   *
   * \return true for success or false for failure.
   */

Best regards.

FernandoGarcia commented 2 years ago

Looks like it doesn't works too.

I tried:

      String filePath = folder + "/" + String(currentFile);
      LOG(F("Full path: "));
      LOGLN(filePath);

      if(file.remove(filePath.c_str()))
      {
        LOG(currentFile);
        LOGLN(F(" was deleted"));
      }
      else
      {
        LOG(currentFile);
        LOGLN(F(" wasn't deleted"));
      }

The output is:

The folder veiculos exists

The folder veiculos is open

Full path: veiculos/175628d2.txt

175628d2.txt wasn't deleted

Full path: veiculos/20fb6e1b.txt

20fb6e1b.txt wasn't deleted
greiman commented 2 years ago

Here is proof that remove and rmdir work for "veiculos/175628d2.txt"

I created the folder and file on an SD then ran this program:

#include "SdFat.h"
SdFat sd;
File file;
void setup() {
  Serial.begin(9600);
  while(!Serial) {}
  Serial.println("Type any to continue");
  while (!Serial.available()) {}
  if (!sd.begin(SS)) sd.initErrorHalt(&Serial);
  Serial.println("ls before:");
  sd.ls("/", LS_R | LS_A);
  if (!sd.remove("veiculos/175628d2.txt")) sd.errorHalt("remove failed");
  if (!sd.rmdir("veiculos")) sd.errorHalt("rmdir failed");
  Serial.println("ls after:");
  sd.ls("/", LS_R | LS_A);
  Serial.println("Done");
}
void loop() {}

The output:

Type any to continue
ls before:
System Volume Information/
  IndexerVolumeGuid
  WPSettings.dat
veiculos/
  175628d2.txt
ls after:
System Volume Information/
  IndexerVolumeGuid
  WPSettings.dat
Done
FernandoGarcia commented 2 years ago

sd.remove() worked with your code but rmdir() doesn't. :(

There's about 100 files in "veiculos" folder.

bugsd

Thanks for your patience!

FernandoGarcia commented 2 years ago

Can you try my code using the function openNext() and getName() with this files please? veiculos.zip

greiman commented 2 years ago

You must delete all files from a folder before calling rmdir.

I am closing this since I have no time to debug your program.

FernandoGarcia commented 2 years ago

Thank you for try help me.

Maybe you should change this comment in your source code.

bool rmdir() ---> Recursively delete a directory and all contained files.

greiman commented 2 years ago

The comment is for rmRfStar(), not rmdir!

/** Recursively delete a directory and all contained files.
   *
   * This is like the Unix/Linux 'rm -rf *' if called with the root directory
   * hence the name.
   *
   * Warning - This will remove all contents of the directory including
   * subdirectories.  The directory will then be removed if it is not root.
   * The read-only attribute for files will be ignored.
   *
   * \note This function should not be used to delete the 8.3 version of
   * a directory that has a long name.  See remove() and rmdir().
   *
   * \return true for success or false for failure.
   */
  bool rmRfStar();
FernandoGarcia commented 2 years ago

Ok, my fault sorry.

FernandoGarcia commented 2 years ago

Hi!

I was trying to understand why the remove() function was working in other part of my program and I have noticed that I was using SD.remove() instead file.remove() as in your proof code.

I have no idea why remove() works with SdFat instance (?) but doesn't works with File. I think do you know.

So the final solution is:

      String filePath = folder + "/" + String(currentFile);
      LOG(F("Full path: "));
      LOGLN(filePath);

      if(SD.remove(filePath.c_str()))
      {
        LOG(currentFile);
        LOGLN(F(" was deleted"));
      }
      else
      {
        LOG(currentFile);
        LOGLN(F(" wasn't deleted"));
      }

Thanks for your help.

Best regards.

FernandoGarcia commented 2 years ago

Final code is:

#include <SdFat.h>

SdFat SD;
File file;
File root;

String folder = "veiculos";

#define LOG(...) Serial.print(__VA_ARGS__)
#define LOGLN(...) Serial.println(__VA_ARGS__)

void setup() {
  SD.begin (SPI_QUARTER_SPEED, 53);
  Serial.begin(115200);

  char currentFile[15];

  if (!root.open(folder.c_str()))
  {
    LOG(F("Can't open the folder "));
    LOGLN(folder);
  }
  else
  {
    LOG(F("The folder "));
    LOG(folder);
    LOGLN(F(" is open"));
  }

  while (file.openNext(&root, O_RDONLY))
  {
    file.getName(currentFile, 15);
    file.close();

    String filePath = folder + "/" + String(currentFile);

    if (SD.remove(filePath.c_str()))
    {
      LOG(currentFile);
      LOGLN(F(" was deleted"));
    }
    else
    {
      LOG(currentFile);
      LOGLN(F(" wasn't deleted"));
    }
  }

  if (SD.rmdir(folder))
  {
    LOG(F("The folder "));
    LOG(folder);
    LOGLN(F(" was deleted."));
  }
  else
  {
    LOG(F("The folder "));
    LOG(folder);
    LOGLN(F(" wasn't deleted"));
  }

}

void loop() {}
greiman commented 2 years ago

I have no idea why remove() works with SdFat instance (?) but doesn't works with File. I think do you know.

If you open a file O_RDONLY file.remove() will fail.

FernandoGarcia commented 2 years ago

Doesn't so much sense to me because the file was closed before try remove.

Could you add the code above as example? Is not easy to find an example to remove file by file like this.

greiman commented 2 years ago

The file must be open for write to delete with file.remove()

Here is an example that removes all files in a directory. The file names are 0.TXT through some max number like 123.TXT

/*
 * remove all files in dir.
 */
void deleteFiles(FatFile* dir) {
  char name[32];
  file_t file;

  // open and delete files
  for (uint16_t n = 0; ; n++){
     sprintf(name, "%u.TXT", n);

     // open start time
     uint32_t t0 = millis();

     // assume done if open fails
     if (!file.open(dir, name, O_WRONLY)) return;

     // open end time and remove start time
     uint32_t t1 = millis();
     if (!file.remove()) error("file.remove failed");

     // remove end time
     uint32_t t2 = millis();

     Serial.print(F("RM "));
     Serial.print(n);
     Serial.write(' ');

     // open time
     Serial.print(t1 - t0);
     Serial.write(' ');

     // remove time
     Serial.println(t2 - t1);
  }
}
FernandoGarcia commented 2 years ago

Ok, thanks!