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库的支持)。