如何在扫描目录中的文件时跳过文件

时间:2018-05-16 19:09:48

标签: c

我有一个列出目录中所有文件的程序。如果文件被断开链接,我想跳过该文件并继续扫描文件中的其他文件。如果有人能指出我错在哪里,我将非常感激。以下是我的代码的一部分

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

继续直到最后一个文件。

2 个答案:

答案 0 :(得分:5)

您的问题应该有一些MCVE。另见inode(7)& symlink(7)。阅读Advanced Linux Programming或更新的内容。

考虑使用nftw(3)fts(3)(如果需要递归扫描子目录)或至少使用文件路径执行stat(2)(因为您正在扫描当前目录,不需要构建该文件路径)。请务必跳过...的条目;所以也许尝试

 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...
 } 

您可能希望处理许多情况。另见errno(3)。对自己的符号链接怎么样?怎么样unix(7)套接字? fifo(7) - S?权限?

(我们没有时间和空间来解释所有细节;你需要阅读很多)

答案 1 :(得分:2)

通常,如果你有

d = opendir(dirname);
while((dir = readdir(d)) != NULL) {
    some_operation(dir->d_name);
}
some_operation 每个 d_name都会失败,因为您应该传递给some_operation的路径是${dirname}/${dir->d_name},而不仅仅是{{1} }}

但是,您的程序通过硬连线将特殊目录dir->d_name传递给.;当你这样做时, 可以安全地仅将opendir传递给dir->d_name,因为some_operation始终是当前的工作目录。问题是. 在应用于损坏的符号链接时不会失败,但 在应用于不是符号链接的目录条目时失败 。如果您在错误消息中包含readlinkdir->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] 联机帮助页并发现它在应用于不是符号链接的内容时会返回readlink

检测损坏的符号链接的正确方法是观察EINVAL成功但lstat失败stat

ENOENT

如果您不需要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 */ } } } 案例中,不要忽视与lstatstat完成整个舞蹈,否则当你试图跑步时,你会感到难过您的程序在没有报告d_type信息的文件系统上。