• ベストアンサー

ディレクトリの判別

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

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

  • ベストアンサー
  • terra5
  • ベストアンサー率34% (574/1662)
回答No.3

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言語でディレクトリが扱えないとか、こんな程度で限界ということはありません。

mirror-name
質問者

補足

お返事有難うございます。一番上のソースコードに加えて、 --------------------------------------------- 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系がいけないんでしょう。

その他の回答 (3)

  • parapa
  • ベストアンサー率15% (42/273)
回答No.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系を対象にした本を参考にして 作りました。

mirror-name
質問者

補足

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

  • osamuy
  • ベストアンサー率42% (1231/2878)
回答No.2

S_ISDIR の定義を確認してみては。 Mac OS X(Tiger)付属のsys/stat.hですと、 if ( S_ISDIR( fi.st_mode ) ){ /* ディレクトリの場合 */ } ――が正しい判定法です。

mirror-name
質問者

補足

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

  • bacet14
  • ベストアンサー率50% (7/14)
回答No.1

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

参考URL:
http://www.linux.or.jp/JM/html/LDP_man-pages/man2/stat.2.html
mirror-name
質問者

補足

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

関連するQ&A