みんなの「教えて(疑問・質問)」にみんなで「答える」Q&Aコミュニティ

こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

ディレクトリの判別

FreeBSD5.4でstat()関数のS_ISDIRを使ってディレクトリかどうかを判別したいのですが、
S_ISDIRでは普通のファイルもディレクトリと認識してしまいます。もしご存知の方がいらっしゃいましたら、何卒ご教授くださいませ。
---------------------------------------------
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <stdlib.h>
int createFileList(char *directoryName){
DIR *directoryId;
struct dirent *directoryPointer;
struct stat fi;

directoryId=opendir(directoryName);
while((directoryPointer=readdir(directoryId))!=NULL){

stat(directoryPointer->d_name,&fi);
if (!S_ISDIR(fi.st_mode)) printf("%s\n",directoryPointer->d_name);

}
closedir(directoryId);
return 0;
}

---------------------------------------------

投稿日時 - 2005-10-28 20:08:20

QNo.1742005

暇なときに回答ください

質問者が選んだベストアンサー

int createFileList(char *directoryName){
で、カレントディレクトリのファイル(ディレクトリ)以外を指定すると、おそらく意図しない動作になります。
d_nameにはフルパス名ではないですし、stat()にそのまま渡すとカレントディレクトリから探しますし。

stat()でエラーしていれば-1が帰ってくるのでちゃんとチェックしてみてください。

具体的にどういうディレクトリでどういうパラメタを渡してどういう結果がになったかを書いたほうがいいでしょう。
自分で判断した結果を書くとそれが間違いだった場合、他の人には間違った情報を伝えることになるので、
正しい回答は得られません。


例えば、カレントディレクトリが/home/mirror-nameでcreateFileList("/tmp/")実行し、
/tmp/dummy.txtというファイルがあれば、
d_nameは"dummy.txt"となり、stat()を実行すると
/home/mirror-name/dummy.txtの情報を得ようとします。
この時にファイルがなければエラーとなり、fiの内容は正しく設定されないことになります。


C言語でディレクトリが扱えないとか、こんな程度で限界ということはありません。

投稿日時 - 2005-10-29 01:20:47

補足

お返事有難うございます。一番上のソースコードに加えて、
---------------------------------------------
int main(int argc,char *argv[]){
createFileList(argv[1]);
return 0;
}
---------------------------------------------
を付け足して、
localhost# gcc -o directoryDistinction directoryDistinction.c

でコンパイル後、
localhost#./directoryDistinction /home/sampleuser/public_html
などで実行しました。
いろいろ試してみると「/」 では正常に判別できるのに階層が深くなるディレクトリだと通常ファイルも全てがディレクトリと判別してしまうようです。

自分もC言語は大好きです。。。きっとUNIX系がいけないんでしょう。

投稿日時 - 2005-10-29 11:06:33

ANo.3

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(4)

ANo.4

#include<sys/dir.h>
#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<sys/stat.h>

main()
{
DIR *dp;
struct direct *dir;
struct stat sbuf;
int i;
size_t size;
char *aa;
char *buf;

if( ( dp = opendir(".") ) == NULL ){
fprintf(stderr,"cannot open directory.\n");
exit(1);
}

getcwd( aa,255);
/*printf("現在のディレクトリーは、(%s)です。\n",aa);*/
i =0;

while( ( dir = readdir(dp) ) != NULL ){

if( dir->d_ino == 0 )
continue;
stat( dir->d_name, &sbuf);
switch( sbuf.st_mode & S_IFMT ){
case S_IFDIR:
printf("<d>");
break;
default:
printf("<f>");
}
if( i > 2 ){
printf("%s\n",dir->d_name);
i = 0;
}else{
printf("%-10s",dir->d_name);
if(strlen(dir->d_name) >= 10 )
printf("\n");
i++;
}
}
printf("\n");
closedir(dp);
exit(0);
}

昔なにげに作ったプログラムです。
31行目のswitchからがファイルかディレクトリかの
判別部分です。
Linuxでは動いた記憶があります。
ただ参考にした本がアスキー出版社のUNIX Cプログラミング
と言う本で本来Linuxを対象にした物でなくて
SystemV系・BSD系を対象にした本を参考にして
作りました。

投稿日時 - 2005-10-29 02:24:12

補足

お返事有難うございます。やはり実行結果は同じに、
階層が深いディレクトリだと通常ファイルなど全てのファイルに<d>がつきます。しかし<d>や<f>がついて非常に見やすかったので、下の人の補足ができました。有難うございます。やはりUnixやLinuxでは難しいのかな?

投稿日時 - 2005-10-29 11:17:45

ANo.2

S_ISDIR の定義を確認してみては。
Mac OS X(Tiger)付属のsys/stat.hですと、

if ( S_ISDIR( fi.st_mode ) ){ /* ディレクトリの場合 */ }

――が正しい判定法です。

投稿日時 - 2005-10-28 22:24:56

補足

お返事有難うございます。早速/usr/include/sys/stat.hをgrep S_ISDIRしてみました。
#define S_ISDIR(m) (((m) & 0170000) == 0040000)
となっていまして、使用法にかんしては・・よく分かりません。。書籍やサイトなどで紹介されている使用方法をとっているので間違いはないとは思います。
やはりC言語の限界なのでしょうか?

投稿日時 - 2005-10-28 22:41:21

ANo.1

条件判定部分を
if ((fi.st_mode & S_IFMT == S_IFDIR))
としてはどうでしょうか。

参考URL:http://www.linux.or.jp/JM/html/LDP_man-pages/man2/stat.2.html

投稿日時 - 2005-10-28 22:15:06

補足

お返事有難うございます。
早速やってみましたが、やはりディレクトリも通常ファイルも表示されませんでした。
FedoraCore4でも同じ結果でした。やはり、C言語ではディレクトリは扱えないのでしょうか?

投稿日時 - 2005-10-28 22:32:55

あなたにオススメの質問