8

我无法识别 stat 引发的错误。以下程序读取目录中的所有文件并打印文件名:

DIR *dp;
struct dirent *dirp;
struct stat sb;

if((dp = opendir(argv[1]))==NULL)
{
    perror("can't open dir");
}
while((dirp = readdir(dp))!=NULL)
{
    if (stat(dirp->d_name, &sb) == -1) {
        perror("stat");
    }   
    printf("File name:               %s \n",dirp->d_name);
}

样本输出:

/home/eipe
stat error: No such file or directory
File name:               copyofsample 
File name:               a.out 
File name:               . 
stat error: No such file or directory
File name:               udpclient.c 
File name:               .. 
stat error: No such file or directory
File name:               client.c 
stat error: No such file or directory
File name:               ftpclient.c 

以下是内容:

ls -l /home/eipe/c

-rwxr-xr-x 1 eipe egroup 7751 2011-02-24 15:18 a.out
-rw-r--r-- 1 eipe egroup  798 2011-02-24 13:50 client.c
-rw-r--r-- 1 eipe egroup   15 2011-02-24 15:34 copyofsample
-rw-r--r-- 1 eipe egroup 1795 2011-02-24 15:33 ftpclient.c
-rw-r--r-- 1 eipe egroup  929 2011-02-24 13:34 udpclient.c
4

2 回答 2

17

dirp->d_name是目录中文件的名称:例如"udpclient.c". 因此,文件的全名是"/home/eipe/c/udpclient.c"- 但您当前的工作目录是/home/eipe,因此stat()正在尝试访问"/home/eipe/udpclient.c",它不存在。

您可以将工作目录更改为argv[1]using chdir(),也可以argv[1]在调用之前将每个文件名添加到stat().

于 2011-02-26T09:15:46.160 回答
3

请注意,POSIX 2008 引入了相关函数(系统调用),所有函数都通过熟悉的函数名称的后缀来fstatat()区分。at它还定义dirfd()了获取与目录流关联的文件描述符。

这些*at()函数采用一个(或两个在的情况下renameat())引用目录的打开文件描述符。这意味着在支持的系统上,另一种编码方式fstatat()是:

const char *name = argv[i];

DIR *dp = opendir(dirname);
if (dp == NULL)
{
    fprintf(stderr, "failed to open directory %s (%d: %s)\n",
            name, errno, strerror(errno));
    return -1;
}

int dfd = dirfd(dp);    /* Very, very unlikely to fail */

struct dirent *dirp;
while ((dirp = readdir(dp)) != NULL)
{
    struct stat sb;
    if (fstatat(dfd, dirp->d_name, &sb, 0) == -1) {
        fprintf(stderr, "fstatat(\"%s/%s\") failed (%d: %s)\n",
                name, dirp->d_name, errno, strerror(errno));
    }
    else
        printf("%-20s %s/%s\n", "File name:", name, dirp->d_name);
}

Usingfstatat()和相关函数允许您使用相对路径名而不使用chdir()(这是危险的;如果不使用,很难回到您开始的位置fchdir()),或者连接名称,如主要接受的答案中所示。为了可移植性,无论如何还是建议使用串联——但我能够使用下面的代码在 Mac OS X (10.10.1) 和 Linux (Ubuntu 14.04) 上进行测试。

开发成完整的程序(test-fstatat.c):

/* SO 0512-5919 */
#define _XOPEN_SOURCE 700   /* POSIX 2008 plus ... */
#include <dirent.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>

int main(int argc, char **argv)
{

    if (argc < 2)
    {
        fprintf(stderr, "Usage: %s directory [...]\n", argv[0]);
        return -1;
    }

    for (int i = 1; i < argc; i++)
    {
        const char *name = argv[i];

        DIR *dp = opendir(name);
        if (dp == NULL)
        {
            fprintf(stderr, "failed to open directory %s (%d: %s)\n",
                    name, errno, strerror(errno));
            return -1;
        }

        int dfd = dirfd(dp);    /* Very, very unlikely to fail */

        printf("%-20s %s\n", "Directory:", name);

        struct dirent *dirp;
        while ((dirp = readdir(dp)) != NULL)
        {
            struct stat sb;
            if (fstatat(dfd, dirp->d_name, &sb, 0) == -1) {
                fprintf(stderr, "fstatat(\"%s/%s\") failed (%d: %s)\n",
                        name, dirp->d_name, errno, strerror(errno));
            }
            else
                printf("%-20s %s/%s\n", "File name:", name, dirp->d_name);
        }

        closedir(dp);
    }
    return 0;
}

样品运行:

$ test-fstatat ~/bin/JLSS-Dist/RCS ../../../src/sqltools/idsmon
Directory:           /Users/jonathanleffler/bin/JLSS-Dist/RCS
File name:           /Users/jonathanleffler/bin/JLSS-Dist/RCS/.
File name:           /Users/jonathanleffler/bin/JLSS-Dist/RCS/..
File name:           /Users/jonathanleffler/bin/JLSS-Dist/RCS/mkbod.sh,v
File name:           /Users/jonathanleffler/bin/JLSS-Dist/RCS/jlssdist.jdc,v
File name:           /Users/jonathanleffler/bin/JLSS-Dist/RCS/old.msd.sh,v
File name:           /Users/jonathanleffler/bin/JLSS-Dist/RCS/chksumtool.pl,v
File name:           /Users/jonathanleffler/bin/JLSS-Dist/RCS/msd2nmd.pl,v
File name:           /Users/jonathanleffler/bin/JLSS-Dist/RCS/mknmd.sh,v
File name:           /Users/jonathanleffler/bin/JLSS-Dist/RCS/publictimestamp.sh,v
File name:           /Users/jonathanleffler/bin/JLSS-Dist/RCS/new.mknmd.sh,v
File name:           /Users/jonathanleffler/bin/JLSS-Dist/RCS/PRODCODE,v
File name:           /Users/jonathanleffler/bin/JLSS-Dist/RCS/prodverstamp.sh,v
File name:           /Users/jonathanleffler/bin/JLSS-Dist/RCS/md5.create.pl,v
File name:           /Users/jonathanleffler/bin/JLSS-Dist/RCS/jdcrelease.sh,v
File name:           /Users/jonathanleffler/bin/JLSS-Dist/RCS/JLSS-Dist.mk,v
File name:           /Users/jonathanleffler/bin/JLSS-Dist/RCS/PRODUCT,v
File name:           /Users/jonathanleffler/bin/JLSS-Dist/RCS/msd.create.sh,v
File name:           /Users/jonathanleffler/bin/JLSS-Dist/RCS/distribution.mk,v
File name:           /Users/jonathanleffler/bin/JLSS-Dist/RCS/nmd.create.sh,v
File name:           /Users/jonathanleffler/bin/JLSS-Dist/RCS/jlss.sh,v
File name:           /Users/jonathanleffler/bin/JLSS-Dist/RCS/VERSION,v
File name:           /Users/jonathanleffler/bin/JLSS-Dist/RCS/cvtjdc.sh,v
File name:           /Users/jonathanleffler/bin/JLSS-Dist/RCS/redonmd.sh,v
File name:           /Users/jonathanleffler/bin/JLSS-Dist/RCS/updmsd.sh,v
File name:           /Users/jonathanleffler/bin/JLSS-Dist/RCS/setnmd.sh,v
File name:           /Users/jonathanleffler/bin/JLSS-Dist/RCS/list2msd.pl,v
File name:           /Users/jonathanleffler/bin/JLSS-Dist/RCS/chkmsdnmd.sh,v
File name:           /Users/jonathanleffler/bin/JLSS-Dist/RCS/vercmp.pl,v
File name:           /Users/jonathanleffler/bin/JLSS-Dist/RCS/MSD.sh,v
File name:           /Users/jonathanleffler/bin/JLSS-Dist/RCS/setjdcversion.sh,v
File name:           /Users/jonathanleffler/bin/JLSS-Dist/RCS/sortnmd.sh,v
File name:           /Users/jonathanleffler/bin/JLSS-Dist/RCS/gennmd.sh,v
File name:           /Users/jonathanleffler/bin/JLSS-Dist/RCS/md5.verify.pl,v
File name:           /Users/jonathanleffler/bin/JLSS-Dist/RCS/setbomversion.sh,v
File name:           /Users/jonathanleffler/bin/JLSS-Dist/RCS/chkbodlst.sh,v
File name:           /Users/jonathanleffler/bin/JLSS-Dist/RCS/updnmd.sh,v
File name:           /Users/jonathanleffler/bin/JLSS-Dist/RCS/domsd.sh,v
File name:           /Users/jonathanleffler/bin/JLSS-Dist/RCS/md5.chksum.pl,v
File name:           /Users/jonathanleffler/bin/JLSS-Dist/RCS/bomrelease.pl,v
File name:           /Users/jonathanleffler/bin/JLSS-Dist/RCS/mkmsd.sh,v
File name:           /Users/jonathanleffler/bin/JLSS-Dist/RCS/fixnmd.sh,v
Directory:           ../../../src/sqltools/idsmon
File name:           ../../../src/sqltools/idsmon/.
File name:           ../../../src/sqltools/idsmon/..
File name:           ../../../src/sqltools/idsmon/idstest.c
File name:           ../../../src/sqltools/idsmon/idslen
File name:           ../../../src/sqltools/idsmon/install-sh
File name:           ../../../src/sqltools/idsmon/scatterinfo
File name:           ../../../src/sqltools/idsmon/ltmain.sh
File name:           ../../../src/sqltools/idsmon/idsmon.msd
File name:           ../../../src/sqltools/idsmon/idsmon.o
File name:           ../../../src/sqltools/idsmon/configure
File name:           ../../../src/sqltools/idsmon/genscatter
File name:           ../../../src/sqltools/idsmon/config
File name:           ../../../src/sqltools/idsmon/idspacket
File name:           ../../../src/sqltools/idsmon/genconnpacket
File name:           ../../../src/sqltools/idsmon/Makefile
File name:           ../../../src/sqltools/idsmon/config.h.in
File name:           ../../../src/sqltools/idsmon/config.guess
File name:           ../../../src/sqltools/idsmon/depcomp
File name:           ../../../src/sqltools/idsmon/sqlihexdump.o
File name:           ../../../src/sqltools/idsmon/missing
File name:           ../../../src/sqltools/idsmon/install.mk
File name:           ../../../src/sqltools/idsmon/sqlihexdump
File name:           ../../../src/sqltools/idsmon/RCS
File name:           ../../../src/sqltools/idsmon/Makefile.am
File name:           ../../../src/sqltools/idsmon/test.istar.logs.tar.gz
File name:           ../../../src/sqltools/idsmon/idstest.o
File name:           ../../../src/sqltools/idsmon/esqlc.mk
File name:           ../../../src/sqltools/idsmon/config.sub
File name:           ../../../src/sqltools/idsmon/idspacket.o
File name:           ../../../src/sqltools/idsmon/compile
File name:           ../../../src/sqltools/idsmon/Old.Releases
File name:           ../../../src/sqltools/idsmon/esqlc-nosfx.mk
File name:           ../../../src/sqltools/idsmon/osiris_11
File name:           ../../../src/sqltools/idsmon/config.h.in~
File name:           ../../../src/sqltools/idsmon/idstest
File name:           ../../../src/sqltools/idsmon/idsmon.c
File name:           ../../../src/sqltools/idsmon/acr.decode
File name:           ../../../src/sqltools/idsmon/sqlihexdump.dSYM
File name:           ../../../src/sqltools/idsmon/toru.istar
File name:           ../../../src/sqltools/idsmon/dumpdblflt
File name:           ../../../src/sqltools/idsmon/sqlipacket.c
File name:           ../../../src/sqltools/idsmon/toru
File name:           ../../../src/sqltools/idsmon/data.info.tgz
File name:           ../../../src/sqltools/idsmon/idsmon.nmd
File name:           ../../../src/sqltools/idsmon/idsmon.jdc
File name:           ../../../src/sqltools/idsmon/idsmon
File name:           ../../../src/sqltools/idsmon/idsmon.black_19
File name:           ../../../src/sqltools/idsmon/Makefile.in
File name:           ../../../src/sqltools/idsmon/aclocal.m4
File name:           ../../../src/sqltools/idsmon/sqlihexdump.c
File name:           ../../../src/sqltools/idsmon/dumpdblflt.dSYM
File name:           ../../../src/sqltools/idsmon/dumpdblflt.c
$
于 2014-12-24T20:30:18.040 回答