• ベストアンサー

ディレクトリの判別

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

  • UNIXの勉強

    下のようなディレクトリ中のファイルを出力するプログラムを作りました #include <sys/types.h> #include <dirent.h> #include "ourhdr.h" int main(int argc, char *argv[]) { DIR *dp: struct direct *dirp; if (argc != 2) err_quit("a single argument (the directory name) is required"); if ( (dp = opendir(argv[1]) ) == NULL) err_sys("can't open %s", argv[1]); while ( (dirp = readdir(dp) ) !=NULL) printf("%s\n", dirp->d_name); closedir(dp); exit(0); } windowsのcygwinでコンパイラしようとしたのですが、 ourhdr.h : NO such file or directory のように表示されコンパイルできません。どうすれば、コンパイルできるようになるのか教えてください。

  • [C言語]トラバースするプログラム(linux)

    linux(ubuntu11.04)でコマンドラインからもらったディレクトリをトラバースするプログラムを作りたいんですがうまくいきません。 一応書けたのですがどうも予想と違う動きをしてしまいます。 #include<stdio.h> #include<stdlib.h> #include<sys/types.h> #include<sys/stat.h> #include<dirent.h> #include<string.h> static void do_traverse(char *patht, int t); int main(int argc, char *argv[]) { int i; if(argc<2) { fprintf(stderr,"%s: no arguments\n",argv[0]); exit(1); } for(i=1;i<argc;i++) { do_traverse(argv[i],0); } return 0; } static void do_traverse(char *path, int t) { DIR *d; struct dirent *ent; int i; d=opendir(path); if(!d) { perror(path); exit(1); } while((ent=readdir(d))!=NULL) { struct stat st; if(lstat(ent->d_name,&st)<0) { perror(ent->d_name); exit(1); } for(i=0;i<t;i++) { printf(" "); } printf("%s\n",ent->d_name); if((strcmp(".",ent->d_name))==0 || (strcmp("..",ent->d_name))==0 || S_ISLNK(st.st_mode)) { continue; } if(S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode)) { do_traverse(ent->d_name,t+1); } } closedir(d); } 例えばディレクトリaにファイルbとディレクトリcがあり、ディレクトリcの中にはファイルdとディレクトリeがあり、ディレクトリeの中にはファイルfがあるとします。 僕の理想では $./traverse a とすると .. . b c .. . d e .. . f となるはずなんですが(表示の順番は適当です)、実際は b .. . c となってしまいうまくトラバースしてくれません どうしてこうなるかわかりません 誰か助けてください お願いします

  • ディレクトリ内のファイル名取得

    maruchan と言うものです。 よろしくお願いします。 さっそく質問 環境 cygwin gcc version 3.3.1 やりたい処理は、ディレクトリ内の全てのファイル名を取得したいと思っています。 内容を見ると単純ですが、そのファイルの数が約10万ファイルぐらいありまして・・・ファイル名を取得するだけで結構な時間が掛かってしまいます。 そこで 私が質問したいのは 高速にファイル名を取得する方法はないのか知りたいです。 私が書いたサンプルです。 /*******************/ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <dirent.h> int fileSelector (const struct dirent *entry); int main(void) { int i = 0; int dirCnt = 0; struct dirent **dp = NULL; char dirPath[256]; strcpy(dirPath, "./file/"); dirCnt = scandir(dirPath, &dp, fileSelector, alphasort); for(i=0; i < dirCnt; i++) { /* 本来はここでファイル名を何かに登録する */ dp[i]->d_name; } free(dp); return 0; } int fileSelector (const struct dirent *entry) { if (strcmp (entry->d_name, ".") == 0 || strcmp (entry->d_name, "..") == 0) { return 0; } return 1; } /*******************/

  • ディレクトリを表示

    初心者ですみません。 そのディレクトリにある画像だけをリンクさせて表示したいのですが <?php $curdir = opendir("."); while($name = readdir($curdir)){ print "<a href=\"./{$name}\">画像</a>\n"; } closedir($curdir); ?> とやると.や..やindex.phpまで表示されてしまいます。 if文やwhileをネストしても消えません。 是非画像だけ表示させる方法を教えて下さい。。。

    • ベストアンサー
    • PHP
  • UNIXの"find"コマンド同等のプログラム作成について

    お世話になっております。 現在UNIXの"-type f"オプションのついた"find"コマンドと同等のプログラムをC言語で作ろうとしています。 つまりディレクトリ内のファイル(サブディレクトリ内のファイル含む、ディレクトリは除外)を全てフルパスで表示するプログラムです。 現在下記の関数を作成したのですがうまく動いてくれません。 どなたかご教授いただけないでしょうか。 【問題】 プログラム内の(**)前後で"dir1"が変更される。 (**)前:"/ディレクトリA/" (**)後:"/ディレクトリA/ディレクトリA内のファイル1" 本当は"dir1"には:"/ディレクトリA/"のままであってほしいです。 "strcat"コマンドの仕様が影響しているのでしょうか。 int _find(char dir1[] , int k ,int l , int m ) { DIR *dir ; struct dirent *dp ; struct stat statbuf ; char txt[1000] ; if ( m == 0 ) l++ ; if ( (dir = opendir(dir1)) == NULL ){ printf("%s",dir1) ; perror("opendir") ; exit(1) ; } for( dp=readdir(dir) ; dp != NULL ; dp=readdir(dir) ){ if ( strcmp(dp->d_name,".") != 0 && strcmp(dp->d_name,"..") != 0 ){ /* ROOT_DIR名-にファイル名を付け加えて、フルパスにする */ strcpy( temp[k][l] , dir1) ; strcat( temp[k][l] , "/" ) ; strcat( temp[k][l] , dp->d_name ) ;  (**) stat( temp[k][l] , &statbuf ) ; if(S_ISDIR(statbuf.st_mode)){ l=_find(temp[k][l],k,l,1) ; }else{ sort[k][l]=temp[k][l] ; printf("temp[%d][%d]=%s\n",k,l,sort[k][l]); printf( "dir5=%s\n",dir1) ; l++ ; } } } closedir(dir) ; return l ; }

  • readdir()で得られるファイル・ディレクトリ情報の順番は?

    Perlプログラムにて、  opendir(DIR, '.');  @dir_list = readdir(DIR);  closedir(DIR); などとすると、そのディレクトリにあるファイルとディレクトリの一覧情報を得ることができますが、この場合、@dir_list にはどのような順番で情報が格納されるのでしょうか? readdir() 関数の仕様が知りたいです。ご存知の方、ぜひ教えてください。

    • ベストアンサー
    • Perl
  • CGIがある場所以外のディレクトリの内容表示方法

    ディレクトリ内にあるファイルの一覧を表示しようとしていますがうまく出来ません。 ---------------- opendir(DIR, "./"); @dir_value = readdir(DIR); closedir(DIR); ---------------- この状態だともちろんですが、CGIがあるディレクトリの一覧を表示します。(この状態で、表示する部分のプログラム(ソース?)が間違っていないことはわかります) この1つ下(同ディレクトリ内に「img」ディレクトリ作成)の内容を表示したいのですが、うまく出来ません。 単純に、 ---------------- opendir(DIR, "./img"); @dir_value = readdir(DIR); closedir(DIR); ---------------- と、してみましたがファイルを表示しません。 他にも、「./img/」または絶対パス(/home/~~)でもだめでした。 下または上のディレクトリを参照するのには上記変更だけでは出来ないのでしょうか? 方法がありましたらお願いします。

    • ベストアンサー
    • CGI
  • ディレクトリ名を取得したい

    perlでディレクトリ名だけを取得したいのですが、 なかなかうまい方法が見つかりません。 ファイル名を取得する・・・というのは結構あるのですが、 ディレクトリ名だけ、というのがどうもわかりません。 ちなみにファイル名取得は以下のようにやっています。 my $md; opendir(DIR, 'q'); while (defined($dir = readdir(DIR))) { $md=substr($dir,0,6); } closedir(DIR); ディレクトリ名だけを取得・・・というのはどうやればよいのでしょうか。

    • ベストアンサー
    • Perl
  • ディレクトリを操作したいと思いdirent.hをインクルードしたのです

    ディレクトリを操作したいと思いdirent.hをインクルードしたのですが「includeファイルを開けません。」と出てコンパイルに失敗してしまいます。 どうすればよいのでしょうか。

  • DIRについて

         DIR *fp; struct dirent *p; fp=opendir(argv[1]); while((p=readdir(fp))!=NULL) といったように、プログラムを組んでいるのですが、 具体的に*fpに入っているもの(指しているもの)は、どのようなものなのでしょうか? *pはdirent構造体を指しているということはわかるのですが、 *fpに関しては、いまいちイメージができないので、 教えていただけないでしょうか?

専門家に質問してみよう