删除C中的文件表明找不到该文件

时间:2012-06-20 13:57:46

标签: c delete-file

我正在处理一个c项目,我需要从目录中删除一个文件。出于某种原因,虽然它继续说它无法删除,因为文件或目录不存在。下面是我用来删除文件的代码。

void deleteOldestLog()
{
    FILE *fp;
    char path[FILE_PATH_BUF_LEN], *fileName;

    fp = popen("ls -tr /home/myfolder/logs/ |head -1", "r");
    if (fp == NULL)
    {
        printf("Failed to run command");
    }
    else
    {
        char removalPath[FILE_PATH_BUF_LEN];
        while ((fileName = fgets(path, sizeof(path)-1, fp)) != NULL)
        {
            sprintf(removalPath, "/home/myfolder/logs/%s", fileName, sizeof(fileName)-1);

            printf("Removing file: %s", removalPath);
            if (remove(removalPath) != 0)
            {
                perror("ERROR DELETING LOG");
            }
            else
            {
                printf("Successfully deleted %s", removalPath);
            }
            break;
        }
        pclose(fp);
    }
}

即使它说它找不到文件因为它不存在我知道这不是真的,因为如果我运行ll后跟c程序打印的路径它返回我想删除的文件。

我认为这可能是因为fgets将'\ 0'放在字符串的末尾,这会阻止删除工作。

我该如何解决这个问题?

1 个答案:

答案 0 :(得分:5)

fgets()读取的文件名末尾有换行符。您的文件名实际上并不以换行符结尾。

您尝试使用以下内容删除换行符:

sprintf(removalPath, "/home/myfolder/%s", fileName, sizeof(fileName)-1);

但是,为了有效,您需要使用strlen()而不是sizeof(),并且您需要修改格式字符串:

sprintf(removalPath, "/home/myfolder/%.*s", (int)strlen(fileName)-1, fileName);

*的参数必须是intstrlen()返回size_t;因此演员。 (如果你打开警告,海湾合作委员会会警告这类事情;至少使用-Wall。)

给你的提示:如有疑问,请打印字符串。我通常会使用这样的格式。请注意字符串周围的尖括号:

printf("Removing: <<%s>>\n", removalPath);

当你看到:

Removing: <</home/myfolder/something
>>

你知道字符串中有换行符有问题。如果没有标记,您可能不会注意到字符串中有换行符导致输出中出现额外的换行符。


  

为什么需要修改格式字符串?

让我们再看一下原来的sprintf()

sprintf(removalPath, "/home/myfolder/%s", fileName, sizeof(fileName)-1);

格式字符串需要1个参数,一个字符串。该调用提供两个值,一个字符串和一个长度。所以,第一个问题是有一个遗留的论点。这通常没有损坏,但要注意它。据推测,传递长度减去一的原因是失去最后一个角色。 printf()系列中的格式可以使用一个或两个数字进行装饰,其中一个或两个都可以使用*而不是整数值。这些数字限制格式化值的长度。当你写:

%.*s

您声明输出的长度应该是在字符串本身之前作为参数传递的int值指定的长度。因此修订:

sprintf(removalPath, "/home/myfolder/%.*s", (int)strlen(fileName)-1, fileName);

(我刚刚在添加此信息时修复了这个问题。)

我也没有将错误检查添加到sprintf()等的输出中。这并不罕见;但是,最佳编码实践确保像sprintf()这样的函数返回您期望的值(这是写入字符串的字符数,不包括尾随空'\0'

(旁白:一般来说,最好使用snprintf()而不是sprintf();这样可以避免缓冲区溢出。

snprintf(removalPath, sizeof(removalPath), "/home/myfolder/%.*s",
         (int)strlen(fileName)-1, fileName);

但是,MSVC下*snprintf()函数的行为与C标准(C99,C11)规定的行为不同。更糟糕的是,在vsnprintf_s()和其他_s函数的情况下,参数列表在MSVC和C标准之间是不同的。)