C语言 当 readdir() 返回文件名时,stat() 错误“没有这样的文件或目录”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5125919/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
stat() error 'No such file or directory' when file name is returned by readdir()
提问by John
I'm not able to identify the error thrown by stat. The below program reads all files in a directory and prints the file name:
我无法识别 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);
}
Sample output:
示例输出:
/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
Here are the contents:
以下是内容:
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
回答by caf
dirp->d_nameis the name of the file in the directory: for example, "udpclient.c". The full name of the file is thus "/home/eipe/c/udpclient.c"- but your current working directory is /home/eipe, so stat()is trying to access "/home/eipe/udpclient.c", which doesn't exist.
dirp->d_name是目录中文件的名称:例如,"udpclient.c". 因此,文件的全名是"/home/eipe/c/udpclient.c"- 但您当前的工作目录是/home/eipe,因此stat()正在尝试访问"/home/eipe/udpclient.c"不存在的 。
You can either change your working directory to argv[1]using chdir(), or you can prepend argv[1]to each filename before you call stat().
您可以将工作目录更改为argv[1]using chdir(),也可以argv[1]在调用stat().
回答by Jonathan Leffler
Note that POSIX 2008 introduces fstatat()and related functions (system calls), all distinguished by the atsuffix to a familiar function name. It also defines dirfd()to get the file descriptor associated with a directory stream.
请注意,POSIX 2008 引入了fstatat()相关的函数(系统调用),所有这些都通过at熟悉的函数名称的后缀来区分。它还定义dirfd()了获取与目录流关联的文件描述符。
The *at()functions take one (or two in the case of renameat()) open file descriptors that refer to a directory. This means that another way of coding this, on a system that supports fstatat()would be:
这些*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);
}
Using fstatat()and related functions allows you to use relative pathnames without using chdir()(which is dangerous; it is hard to get back to where you started without using fchdir()), or concatenating names as shown in the main accepted answer. For portability, it is probably still advisable to use concatenation anyway — but I was able to test this on Mac OS X (10.10.1) and Linux (Ubuntu 14.04), using the code below.
使用fstatat()和相关函数允许您在不使用的情况下使用相对路径名chdir()(这是危险的;如果不使用就很难回到您开始的地方fchdir()),或连接名称,如主要接受的答案所示。为了可移植性,无论如何还是建议使用串联 - 但我能够在 Mac OS X (10.10.1) 和 Linux (Ubuntu 14.04) 上使用下面的代码进行测试。
Developed into a complete program (test-fstatat.c):
开发成完整的程序(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;
}
Sample run:
示例运行:
$ 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
$

