簡體   English   中英

當 readdir() 返回文件名時,stat() 錯誤“沒有這樣的文件或目錄”

[英]stat() error 'No such file or directory' when file name is returned by readdir()

我無法識別 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

dirp->d_name目錄中文件的名稱:例如, "udpclient.c" 因此文件的全名是"/home/eipe/c/udpclient.c"但你當前的工作目錄是/home/eipe ,所以stat()試圖訪問"/home/eipe/udpclient.c" ,它不存在。

您可以使用chdir()將您的工作目錄更改為argv[1] ,或者您可以在調用stat()之前將argv[1]到每個文件名。

請注意,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);
}

使用fstatat()和相關函數允許您在不使用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
$

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM