C 扫描目录中的文件时如何跳过文件
我有一个程序,列出目录中的所有文件。如果某个文件的链接断开,我希望跳过该文件并继续扫描文件中的其他文件。如果有人能指出我错的地方,我将不胜感激。下面是我代码的一部分C 扫描目录中的文件时如何跳过文件,c,C,我有一个程序,列出目录中的所有文件。如果某个文件的链接断开,我希望跳过该文件并继续扫描文件中的其他文件。如果有人能指出我错的地方,我将不胜感激。下面是我代码的一部分 d = opendir("."); while((dir = readdir(d)) != NULL) { char buff[256]; int target = readlink (dir->d_name, buff, sizeof(buff)); if (target == -1) {
d = opendir(".");
while((dir = readdir(d)) != NULL) {
char buff[256];
int target = readlink (dir->d_name, buff, sizeof(buff));
if (target == -1)
{
printf("i found broken link so continuing to next file..\n");
continue;
}
}
我的问题是,它正在打印以下内容,而我只有一个断开的链接
i found broken link so continuing to next file
i found broken link so continuing to next file
i found broken link so continuing to next file
并一直持续到最后一个文件。您的问题应该有一些问题。另见&。阅读或更新的东西 考虑使用或(如果需要递归扫描子目录)或至少对文件路径执行一次扫描(因为您正在扫描当前目录,所以不需要构造该文件路径)。请记住跳过
和的条目。
;所以试试吧
d = opendir(".");
while((dir = readdir(d)) != NULL) {
struct stat mystat;
if (!strcmp(dir->d_name, ".") || !strcmp(dir->d_name, "..")) continue;
memset (&mystat, 0, sizeof(mystat));
if (stat(dir->d_name, &mystat) || S_ISLNK(mystat.st_mode))
continue;
/// etc...
}
您可能需要处理许多情况。另见。自我符号链接怎么样?插座呢-s权限
(我们没有时间和空间来解释所有细节;你确实需要大量阅读)通常,如果你有
d = opendir(dirname);
while((dir = readdir(d)) != NULL) {
some_operation(dir->d_name);
}
some_操作
将在每次d_name
时失败,因为您应该传递到some_操作
的路径是${dirname}/${dir->d_name}
,而不仅仅是dir->d_name
但是,您的程序通过硬连线将特殊目录
传递到opendir
;这样做时,只需将dir->d_name
传递给一些操作
,这是安全的,因为
始终是当前工作目录。您的问题是,readlink
在应用于损坏的符号链接时不会失败,但在应用于非符号链接的目录条目时会失败。如果您在错误消息中包含dir->d_name
和strerror(errno)
,您自己就可以更容易地解决这个问题,如下所示:
d = opendir(".");
while ((dir = readdir(d)) != 0) {
char buff[256];
if (readlink(dir->d_name, buff, sizeof buff) {
printf("%s: readlink failed: %s\n", dir->d_name, strerror(errno));
} else {
printf("%s -> %s\n", dir->d_name, buff);
}
}
.gnome2: readlink failed: Invalid argument
.python_history: readlink failed: Invalid argument
test.s: readlink failed: Invalid argument
bin -> .local/bin
[etc]
如果这样做,您将得到如下输出:
d = opendir(".");
while ((dir = readdir(d)) != 0) {
char buff[256];
if (readlink(dir->d_name, buff, sizeof buff) {
printf("%s: readlink failed: %s\n", dir->d_name, strerror(errno));
} else {
printf("%s -> %s\n", dir->d_name, buff);
}
}
.gnome2: readlink failed: Invalid argument
.python_history: readlink failed: Invalid argument
test.s: readlink failed: Invalid argument
bin -> .local/bin
[etc]
然后,您可能会想到查看readlink
手册页,发现它在应用于非符号链接的内容时返回EINVAL
检测断开符号链接的正确方法是通过观察lstat
成功,但stat
失败,方法是enoint
:
struct stat lst, st;
if (lstat(dir->d_name, &lst)) {
/* some other kind of problem */
} else if (!S_ISLNK(lst.st_mode)) {
/* not a symlink at all */
} else if (stat(dir->d_name, &st)) {
if (errno == ENOENT) {
/* broken symlink */
} else {
/* some other kind of problem */
}
} else {
/* valid symlink, `lst` tells you about the link,
`st` tells you about what it points to */
}
如果您不需要来自lst
的任何其他信息,并且您的文件系统支持d_type
,则可以跳过lstat
调用:
if (dir->d_type == DT_LNK) {
struct stat st;
if (stat(dir->d_name, &st)) {
if (errno == ENOENT) {
/* broken symlink */
}
}
}
但是在
dtu UNKNOWN
的情况下,不要忽略使用lstat
和stat
来完成整个过程,否则当您试图在一个不报告d_类型信息的文件系统上运行程序时,您会感到悲伤。。。。出现错误时,返回-1,并设置errno以指示错误。
-->EINVAL指定的文件不是符号链接。
请不要只是将人们指向一堆手册页,手册页通常只有在您已经内部化了如何读取它们的情况下才有意义。另外,请推荐fts
而不是nftw
,因为nftw
不能保证线程安全,也可能不支持非常大的目录。@zwol:最肯定的是支持非常大的目录。GNU C库实现是线程安全的,除非其中一个函数(或另一个线程)更改当前工作目录(nftw()
本身不会更改它)。POSIX.1不能保证这一点nftw()
不需要每个深度的描述符;每个深度最多只使用一个。另外,它是POSIX.1-2008,而fts
是特定于BSD的(但恰好受到GNU C库的支持)。