我的代码是这样的:
DIR* pDir = opendir("/path/to/my/dir");
struct dirent pFile = NULL;
while ((pFile = readdir())) {
// Check if it is a .zip file
if (subrstr(pFile->d_name,".zip") {
// It is a .zip file, delete it, and the matching log file
char zipname[200];
snprintf(zipname, sizeof(zipname), "/path/to/my/dir/%s", pFile->d_name);
unlink(zipname);
char* logname = subsstr(zipname, 0, strlen(pFile->d_name)-4); // Strip of .zip
logname = appendstring(&logname, ".log"); // Append .log
unlink(logname);
}
closedir(pDir);
(此代码未经测试,纯粹是一个例子)
重点是:是否允许在使用readdir()循环目录时删除目录中的文件? 或者readdir()仍然会找到已删除的.log文件?
答案 0 :(得分:6)
如果文件被删除或添加到 最近的目录 调用opendir()或rewinddir(), 是否后续调用readdir() 返回该文件的条目是 未指定的。
所以,我猜是......这取决于。
取决于操作系统,在一天中的时间,取决于添加/删除的文件的相对顺序,...
另外,在readdir()
函数返回并尝试unlink()
文件的时间之间,其他一些进程可能已删除该文件而您的unlink()
失败。
修改的
我测试了这个程序:
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
int main(void) {
struct dirent *de;
DIR *dd;
/* create files `one.zip` and `one.log` before entering the readdir() loop */
printf("creating `one.log` and `one.zip`\n");
system("touch one.log"); /* assume it worked */
system("touch one.zip"); /* assume it worked */
dd = opendir("."); /* assume it worked */
while ((de = readdir(dd)) != NULL) {
printf("found %s\n", de->d_name);
if (strstr(de->d_name, ".zip")) {
char logname[1200];
size_t i;
if (*de->d_name == 'o') {
/* create `two.zip` and `two.log` when the program finds `one.zip` */
printf("creating `two.zip` and `two.log`\n");
system("touch two.zip"); /* assume it worked */
system("touch two.log"); /* assume it worked */
}
printf("unlinking %s\n", de->d_name);
if (unlink(de->d_name)) perror("unlink");
strcpy(logname, de->d_name);
i = strlen(logname);
logname[i-3] = 'l';
logname[i-2] = 'o';
logname[i-1] = 'g';
printf("unlinking %s\n", logname);
if (unlink(logname)) perror("unlink");
}
}
closedir(dd); /* assume it worked */
return 0;
}
在我的计算机上,readdir()
找到已删除的文件,但找不到在opendir()
和readdir()
之间创建的文件。但在另一台计算机上可能会有所不同;如果我使用不同的选项编译,我的计算机可能会有所不同;如果我升级内核可能会有所不同; ...
答案 1 :(得分:1)
我正在测试我的新Linux参考书。 Michael Kerrisk的Linux编程接口说明如下:
SUSv3明确指出,未指定readdir()是否将返回自上次调用opendir()或rewinddir()以来最后添加或删除的文件名。自上次此类调用以来既未添加也未删除的所有文件名都将保证返回。
我认为未指明的是尚未扫描的目标会发生什么。一旦条目被退回,100%保证不再退回,无论您是否取消链接当前的目标。
另请注意第二句提供的保证。由于您将单独留下其他文件并且仅取消链接zip文件的当前条目,因此SUSv3保证将返回所有其他文件。日志文件的内容未定义。它可能会或可能不会被readdir()返回,但在你的情况下,它应该是有害的。
我之所以探究这个问题,是为了在exec()之前找到一种在子进程中关闭文件描述符的有效方法。
史蒂文斯在APUE中建议的方法是做以下事情:
int max_open = sysconf(_SC_OPEN_MAX);
for (int i = 0; i < max_open; ++i)
close(i);
但我正在考虑使用类似于OP中的代码来扫描/ dev / fd /目录以确切地知道我需要关闭哪些fds。 (特别注意自己,跳过DIR手柄中的dirfd。)
答案 2 :(得分:0)
我发现以下页面描述了这个问题的解决方案。