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

このQ&Aのポイント
  • ディレクトリ内のファイル名を取得する方法について
  • ファイル名を取得するだけで時間が掛かる問題に対する解決策
  • 高速にファイル名を取得する方法を知りたい
回答を見る
  • ベストアンサー

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

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

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

  • ベストアンサー
  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.4

>(1)だけが異様に時間掛かってました 約17秒ぐらい ファイルのキャッシュが効く2回目以降の実行でもそれほど時間がかかるなら、 dp[]が大量にメモリを消費しますから、 ページアウトしてたりするんじゃないでしょうか?

maruchan0488
質問者

お礼

ここまでつきあって頂き有難うございます。 どちらにしろ この3通りの方法での共通した問題は 初回実行時のキャッシュがない時に時間が掛かってしまうこと これは、もうどうしようもないように思えます。

その他の回答 (3)

  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.3

ウチのcygwin + gcc で実際に簡単なサンプルを書いて実験してみた処 100000コのファイルの探索では、ほとんど有意な差はありませんでした。 (1)scandirを使う方法 (2)readdirを使う方法 (3)パイプでlsからの出力を使う方法 の3つを試してみたのですが、 どれも、1秒未満で終了してしまいます。 何回も試しているので、ファイルアクセスのキャッシュの効果があると思いますが、それほど変わらないようです。 一応 timeコマンドで時間を測定してみた所 (3)>(2)>(1) の様にはなっていました。 単に処理の複雑さが(3)<(2)<(1)になっているためと思われます。

maruchan0488
質問者

補足

実際に実行してくださって ありがとうございます!! やはり 数が数なだけにいちいちソートしてたら 遅くなるのが当たり前ですよね・・・ 私の所では、(2)と(3)が同じくらいの速度で 1秒掛からないくらいでした。 (1)だけが異様に時間掛かってました 約17秒ぐらい

  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.2

#1です 見当違いなことを言ってすみません。 今のプログラムだと、scandirが終了するまで待たないといけないので、こういう部分を別プロセスにすることで、スピードアップが図れるかもしれません。 プログラム的には、実際に別プロセスにするプログラムを書くより ls -l || thisProg のようにパイプを使うのが簡単の様に思います。 windowsの様に、前のコマンドが終わってからしか動かないというようなことが、UNIX系ではないと思いますので、スピードアップが図れると思うのですが、どうでしょうか? 実際に試した訳ではないので、自信はないですけど。

maruchan0488
質問者

お礼

いえいえ よく考えて見ると BLUEPIXYさんの言っていた >>あらかじめ、lsでファイル名のファイルを作っておくのも1つの方法かと思います。 を使えないかと考えていたところ 動的に増えていくファイルだけじゃない所もあるので そこを ファイルリストを作って少しでも負担を軽く出来るように作り直してみます。 パイプの方は、このファイル名が取得出来ないと 次の処理が出来ないのでちょっと難しいです。 出来れば PHPにあるsqliteのような簡単なデータベースが c言語にもあれば一番いいのですが・・・ないですよね?

  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.1

動的に取得する必要がないなら、 あらかじめ、lsでファイル名のファイルを作っておくのも1つの方法かと思います。 検討違いだったらすみません。

maruchan0488
質問者

補足

アドバイスありがとうございます。 すいません私の説明不足でした。 目的のファイルは 結構頻繁に増えるので動的に取りたいと思っています。

関連する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; } ---------------------------------------------

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

    ディレクトリ内にあるすべてのファイルの名前を取得したいのですが、どうすればいいでしょうか? unix系では dirent.h を使ってできるようなのですが windowsなので、dirent.hはないようです。 お願いします。

  • fpus:ファイル操作

    Cを勉強している初心者です。 このソースはコンパイルは通るのですが、 エラーがでてしまいます。 いろいろと調べてみたりもしたのですが わかりませんでした。 なぜなのでしょうか? #include <stdio.h> #include <string.h> struct student{ char name[20]; }; int main(void) { struct student s[1]; int i; int j = 1; FILE *fp; strcpy(s[0].name,"taro"); strcpy(s[1].name,"jiro"); if((fp = fopen("test.txt","w+")) == NULL) { printf("ファイルを開けませんでした\n"); return (-1); } for(i=0;i<=j;i++) { fputs(s[i].name,fp); } fclose(fp); return (0); }

  • fputs:ファイル操作

    Cを勉強している初心者です。 このソースはコンパイルは通るのですが、 エラーがでてしまいます。 いろいろと調べてみたりもしたのですが わかりませんでした。 なぜなのでしょうか? #include <stdio.h> #include <string.h> struct student{ char name[20]; }; int main(void) { struct student s[1]; int i; int j = 1; FILE *fp; strcpy(s[0].name,"taro"); strcpy(s[1].name,"jiro"); if((fp = fopen("test.txt","w+")) == NULL) { printf("ファイルを開けませんでした\n"); return (-1); } for(i=0;i<=j;i++) { fputs(s[i].name,fp); } fclose(fp); return (0); }

  • [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 となってしまいうまくトラバースしてくれません どうしてこうなるかわかりません 誰か助けてください お願いします

  • 昇順ソート

    sort.txtから読み込んだ値を 昇順でソートして出力するにはどうしたらよいでしょうか? #include <stdio.h> #include <stdlib.h> #include <string.h> #include <search.h> /* 比較関数 */ int strcmp_asc(const void *, const void *); int main(void) { FILE *fin, *fout; int i; int length; char s[256], s2[256]; if( (fin=fopen("sort.txt","r"))==NULL) { printf("入力ファイルがオープンできません\n"); exit(EXIT_FAILURE); } if( (fout=fopen("file2.txt","w"))==NULL) { printf("出力ファイルがオープンできません\n"); exit(EXIT_FAILURE); } while(fgets(s, 256, fin) != NULL) { /* 要素数を求める */ length = sizeof(s) / 256; /* 昇順でソート */ qsort(s, length, 256, strcmp_asc); /* memset(s2, NULL, sizeof(s2)); for (i = 0; i < length; i++) { } */ fprintf(fout,"%s\n",s2); } fclose(fin); fclose(fout); return 0; } int strcmp_asc(const void *sa, const void *sb) { return strcmp((char *)sa, (char *)sb); } sort.txt 50 45 35 25 15 10 5 1 32 46 8 7 9 19 18 14 16 13 12 17 11 20 40 30 31 3 2 37 38 36 33 39 34 49 47 48 4 6 44 42 43 41 21 22 26 24 28 29 27 23

  • 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言語 「構造体のソートと結果のファイル出力」 緊急です。助けてください。

    授業で課題が出され内容は以下となってます。 1.歴代アメリカ大統領の情報を構造体とする. 2.ソートを昇順で行うこと 3.結果を出力すること〔参考:http://www-it.sci.waseda.ac.jp/CPR1/class08/kekka.log) 以下が自分で作ってみたものですが、多数のエラーが出てしまいどうしたらいいのか分かりません。。。抜本的な変更でもかまいませんので、分かる方助けてください。 -----作成分------ #include <stdio.h> #include <string.h> struct president { int no, age; char name1[20], name2[20]; /* 氏名 */ }; int main(void) { int i; struct president pre1[44] = { {1,57,"George","Washington"}, {2,61,"John","Adams"}, {3,57,"Thomas","Jefferson"}, //リストが長いので省略// {44,47,"Barack","Obama"}, }; struct president *pres; pres = pre1; //ポインタ// sort(pres, 44, sizeof(struct president), president_cmp);//ソート構文 エラーがでます。。。// printf("---------sortted list by age------- \n # age first last \n");} for (i = 0; i < 44; i++){printf("------------------------------------ \n") printf("%d %d %s %s \n, pres[i]->no, pres[i]->name, pres[i]->name1, pres[i]->name2);} for(i = 0; i < 44; i++) { if (i==0){printf("---------list of presidents---------- \n");//RAW DATAの表示を行ない。ここは問題ないみたいです// printf(" age first last \n");}; printf("%d %d %s %s \n", pres->no, pres->age, pres->name1, pres->name2); ++pres; } return 0; } int president_cmp(const void*p1, const void*p2){ //比較関数// struct president *cmp1 = (struct president*)p1; struct president *cmp2 = (struct president*)p2; return strcmp(cmp1->age, cmp2->age); } ここにファイル出力の分をたしたいのですが、どこにどうすればいいのでしょう。 大変申し訳ありませんが、緊急です!!お願いします。

  • パスを含むファイルリストを表示する際、 ASCIIコード順になるように

    パスを含むファイルリストを表示する際、 ASCIIコード順になるようにソートして表示するようにするプログラムを作っているのですが、リストの仕組がいまいちよくわからず、うまくソートできません。 /* insert_dirent_cell(): セルをリストの先頭に追加する * 引数: head -- リストの先頭のセルへのポインタ * cell -- リストに加えたいセルへのポインタ * 戻り値: リストの先頭のセルへのポインタ */ struct dirent_cell *insert_dirent_cell(struct dirent_cell *head,struct dirent_cell *cell) { struct dirent_cell *ins_buf; //最初に挿入 if(head == NULL) { head = cell; return cell; } //先頭に挿入 if(strcmp(head->name, cell->name) > 0) { cell->next = head; head->next = cell->next->next; return cell; } //途中に挿入 ins_buf = head; while(ins_buf->next != NULL) { if(strcmp(ins_buf->next->name, cell->name) > 0) { cell->next = ins_buf->next; ins_buf->next->next = cell->next->next; return cell; } ins_buf = ins_buf->next; } //最後に挿入 ins_buf->next = NULL; cell->next = ins_buf; return cell; }

  • CTR-Dでプログラムを終了

    学校の課題で、 --- 探索キーとして名前を入力し、入力と一致した場合、その名前と年齢を印字することを繰り返す。 CTR-Dが入力されたとき、プログラムを終了する。 また、文字比較の為に関数strcmpを使用する。 --- という課題が出されたのですが、while(scanf("%s", name) != EOF)を入れるとうまくいきません。 自分で途中までやったものは↓のものです。 どこが違うのか教えてください(>_<) #include<stdio.h> #include<string.h> #define N 10 struct card{ char *name; int age; }; struct card meibo[N] = { "Takahashi", 14, "Kobayashi", 15, "Hosokawa", 17, "Sugimoto", 18, "Sawai", 19, "Itou", 20, "Kawai", 22, "Ishikura", 24, "Oda", 25, "Nakamura", 28 }; int main(void){ char *name; int i; printf("name? : "); scanf("%s", name); while (scanf("%s", name) != EOF){ for (i=0; i<N; i++){ if (strcmp(name, meibo[i].name) == 0) break; } } if (i<N){ printf("%s is %d.\n", meibo[i].name, meibo[i].age);} else{ printf("Not found.\n");} return 0; }

専門家に質問してみよう