我的代码是这样的:
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);
(this代码未经测试,纯粹是一个例子)
关键是:是否允许在使用readdir()遍历目录时删除目录中的文件?或者readdir()仍然会找到已删除的.log文件吗?
3条答案
按热度按时间z4iuyo4d1#
引用自POSIX readdir:
如果在最近一次调用opendir()或rewinddir()之后,从目录中删除或向目录中添加了一个文件,则未指定后续调用readdir()是否返回该文件的条目。
所以,我猜...看情况
它取决于操作系统,在一天中的时间,在文件添加/删除的相对顺序,.
另外,在
readdir()
函数返回和您尝试unlink()
文件之间,其他进程可能已经删除了该文件,而您的unlink()
失败。我测试了这个程序:
在我的计算机上,
readdir()
查找已删除的文件,但找不到在opendir()
和readdir()
之间创建的文件。但在另一台计算机上可能会有所不同;如果我用不同的选项编译,在我的计算机上可能会有所不同;如果我升级内核,情况可能会有所不同;...u91tlkcl2#
我在测试我的新Linux参考书。Linux Programming Interface作者:Michael Kerrisk
SUSv 3明确指出,readdir()是否会返回自上次调用opendir()或rewinddir()以来添加或删除的文件名是未指定的。所有自上次调用以来既没有添加也没有删除的文件名都保证被返回。
我认为,未指明的是尚未扫描的dirents会发生什么。一旦一个条目被返回,100%保证它不会再被返回,无论你是否取消当前目录的链接。
还请注意第二句提供的保证。由于您不需要处理其他文件,而只是取消链接zip文件的当前条目,因此SUSv 3保证将返回所有其他文件。对日志文件发生的操作未定义。它可能会也可能不会被readdir()返回,但在你的情况下,它应该是无害的。
我探索这个问题的原因是为了找到一种有效的方法,在exec()之前关闭子进程中的文件描述符。
Stevens在APUE中建议的方法是:
但是我想使用类似于OP中的代码来扫描/dev/fd/目录,以确切地知道我需要关闭哪些fds。(特别提醒自己,跳过包含在文件句柄中的dirfd。)
raogr8fs3#
我发现下面的页面描述了这个问题的解决方案。
https://web.archive.org/web/20220122122948/https://support.apple.com/kb/TA21420?locale=en_US
未指定的行为是修改目录后readdir()应返回的行为。许多文件系统已经实现了,后续的readdir()调用将返回下一个目录条目。HFS文件系统的实现不能保证使用上述方法删除所有包含的文件或目录。