- 1 名前:名無しさん@お腹いっぱい。 [2005/09/22(木) 20:29:34 ]
- UNIXおよびUNIX clone環境一般のプログラミングに関する質問スレッド
過去スレ(プログラム技術板) Part6 pc8.2ch.net/test/read.cgi/tech/1116908090/ Part5 pc8.2ch.net/test/read.cgi/tech/1105723117/ Part4 pc5.2ch.net/test/read.cgi/tech/1095843584/ Part3 pc5.2ch.net/test/read.cgi/tech/1085930894/ Part2 pc5.2ch.net/test/read.cgi/tech/1055110889/ Part1 pc2.2ch.net/tech/kako/992/992057422.html Part3ミラー makimo.to/2ch/pc5_tech/1085/1085930894.html Part2ミラー makimo.to/2ch/pc5_tech/1055/1055110889.html 関連スレ Cygwin使っている人いますか? その14 (UNIX板) pc8.2ch.net/test/read.cgi/unix/1107587275/ Cygwin使っている人いますか? 3 (Windows板) pc8.2ch.net/test/read.cgi/win/1090131123/ 関連板 Linux板 pc8.2ch.net/linux/ プログラム技術板 pc8.2ch.net/tech/
- 429 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/03/03(火) 09:27:07 ]
- Cのコード中でディレクトリの内容を比較するのはどうしたらいいか悩んでいます。
動作的には "diff -r dirA dirB" を実行した場合の結果と同じ処理をしたいのですが、 毎回 diff コマンドを呼ぶオーバーヘッドを避け、出来ればCのコードで実現したいと 思ってます。どうすべきでしょう? 1. UNIX の API にこの目的にふさわしいものがあり(何という名前?)、それを使う 2. 違うファイルかディレクトリに遭遇するまで地道に両者のディレクトリを辿るような コードを自分で書く 3. diff のソースコードを入手し、自分のプログラムにリンクして使う 4. その他
- 430 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/03/03(火) 09:57:03 ]
- お前の書くコードがdiffよりオーバーヘッドが少ないわけがない。
- 431 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/03/03(火) 10:09:27 ]
- >>429
普通のdiffコマンドは高速でないアルゴリズム( O(ND) )を使ってるから、 gitとかpythonのライブラリに使われてるやつのが速い ってわけで、速度を追い求めるなら差分取得のアルゴリズムについて調べてがんばれ
- 432 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/03/03(火) 10:12:30 ]
- いや高速でないってこたないんですよ、それより速いのがあるだけで
- 433 名前:429 mailto:sage [2009/03/03(火) 10:29:38 ]
- あー書き方が悪かったかな。
もし diff ということで LCS とかそこらへんに脊髄反射されてたらごめんなさい。 自分が知りたいのは dirA と dirB の内容が違うか同じかだけなんです。 この場合むしろディレクトリの階層に効率よくアクセスできることが重要なんじゃないかと 思ったんですが、違います? fts とかですかね? それにファイルを処理するようなソフトならありがちな処理のような気がするので、 どこかに適切なコードのサンプルがあればと思って...
- 434 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/03/03(火) 10:37:16 ]
- >>433
> 自分が知りたいのは dirA と dirB の内容が違うか同じかだけなんです。 内容の比較は必要か タイムスタンプの比較だけでいいか 同じファイル名が存在するだけでいいのか rsync --dry-runの出力結果を使うとか。
- 435 名前:429 mailto:sage [2009/03/03(火) 10:50:52 ]
- >>434
「同じ」とはディレクトリ構造が同じで、その中に存在するファイルの名前&内容が同じ という積もりです。 タイムスタンプは比較しません。 >rsync --dry-runの出力結果を使うとか。 はい、確かにそれも速そうですが、自分のプログラムだと比較的浅いディレクトリに 対してそれを何度も呼ぶことになりそうなので、C の何かの API で書いた方がいいのか なあと。 ある意味 rsync みたいなプログラムなんですが、syncするときにいろいろカスタムな ロジックを入れたいので、コードを書いているといいますか....
- 436 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/03/03(火) 11:32:23 ]
- 内容比較がcmp -sレベルでいいなら、
readdir/lstatで自分で書けばいいんじゃない? 質問せずに書けば、今頃書き終わっている頃かと。
- 437 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/03/03(火) 13:31:30 ]
- ファイルとディレクトリの equality は適当に定義出来
るとして、↓みたいになるかな。 for (File src = each of srcDir) { File dst = dstDir.Find(src); if (dst == null) { // src にしかない } else if (src != dst) { // 違う } } for (File dst = rest of dstDir) { // dst にしかない } each of …は都度 readdir して、Find は保持してるプー ルから探して、無ければ見つかるまで readdir、してプー ルに入れていく感じ。見つかったらプールから削除して おいて rest of …でそれを得る。
- 438 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/03/03(火) 14:07:34 ]
- 両方コレクションにいれて、ソートして、
先頭二つ、計四つを比較しながら取り出せばいい。 四つになるのはどちらが欠けているかわからないから。 どれも違う場合、四つの中で小さいの二つを捨てればいい。 AB AB AB BC BC AB - AB CD AC BD
- 439 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/03/03(火) 14:16:00 ]
- >>438
ファイル/ディレクトリの equality と同様に順序付け も定義出来るなら(ソートするからには出来るはずだ)、 先読みする必要はない。マージソートの要領だ。
- 440 名前:名無しさん@お腹いっぱい。 [2009/03/12(木) 19:41:22 ]
- dirp=opendir(".");
printf("1 :%d;\n",telldir(dirp)); printf("2 :%d;\n",telldir(dirp)); printf("3 :%d;\n",telldir(dirp)); closedir(dirp); とすると返す値は1,2,3とどんどんインクリメントしていくだけだし seekdirは無反応rewinddirは巻き戻すばかりかtelldirをひとつ進めるだけ readdirとかはちゃんとできているんだけれど 何か呪文とかいるのかダメダメな関数なのか情報please
- 441 名前:名無しさん@お腹いっぱい。 [2009/03/12(木) 19:51:28 ]
- >>440 OSはFreeBSDです。
- 442 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/03/12(木) 20:15:55 ]
- たぶん実装がおかしいんだろう。MacOS Xも同様らしい。
ttp://idm.s9.xrea.com/ratio/2007/09/10/000673.html dirent読むのにtelldirやseekdir使うようなやつはいないから放置されてると想像。
- 443 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/03/12(木) 20:24:17 ]
- 追加。このへん関係あるかも。
ttp://www.freebsd.org/cgi/query-pr.cgi?pr=bin/121656
- 444 名前:名無しさん@お腹いっぱい。 [2009/03/12(木) 20:32:49 ]
- >>440です。rewinddirの記述は間違っていました。
rewinddirとreaddirだけが使えます。 で調べたらscandirというのがありました。 mallocしてくれて配列に入れて関数指定すればsortもしてくれるようなので コールバックもsort関数に入れます。 >>435もscandir+lstatでいいのでは? しかしひどすぎるなtelldir+seekdir ファイルの多いディレクトリーでちょろちょろよむもん作りたかったんだけど 一気読みが基本ですか?
- 445 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/03/12(木) 20:38:50 ]
- とりあえずコールバック抜きのアルファソートやってみた。
c = scandir(dirname, &namelist, NULL, alphasort); if(c == -1) { puts("not opendir"); return(1); } printf ("%d\n", c); for (i = 0; i < c; ++i) { printf ("%s\n", namelist[i]->d_name); free(namelist[i]); } free(namelist); opendirの苦労は一体....orz
- 446 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/03/12(木) 20:40:17 ]
- >>435
opendir -> ディレクトリをファイルとして開く readdir -> ディレクトリのエントリを一つ読み込む(ポインタ一個進む) seekdir -> ディレクトリのエントリを x 番目にセットする telldir -> 今いるエントリ位置を報告する を組み合わせて, 双方のエントリを比較して 1. 対象物の inode が同じなら処理スキップ 2. 対象物が ディレクトリなら, 自分自身を再帰的に呼び出す 3. 対象物がファイルなら中身を比較 すればええんちゃう?
- 447 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/03/12(木) 20:46:16 ]
- 既に読んだエントリに戻って読み直すシチュエーションがわからん。
仮にtelldir/seekdirの動作がまともでも、 いちいち物理的にディレクトリ読みに行くような実装だったりしたら、 遅いし最中に誰かがいじらんとも限らんし、いいことなしでは? キャッシュしてるんだとすれば一気読みと何も変わらんし。 というわけで、telldir/seekdirは価値なしなんじゃないかと。
- 448 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/03/12(木) 21:00:32 ]
- >>447
再帰して必要物がなくって、バックトラックするときに 変わってしまった状態を元に戻すために必要 recur_dir(... here = telldir(... if (このエントリが dir && 比較対象と違う) if (recur_dir(...) == succeed) return なんとか ここに戻ってきた場合何がどうなってるか保証できない seekdir(here) 続きの処理
- 449 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/03/12(木) 21:56:26 ]
- 何がどうなってるか保証できない状態なら
telldirしたところにseekdirしても保証できないだろう
- 450 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/03/15(日) 11:44:20 ]
- ストリームとしてファイルリストをチェックしていくならseekとかは必須だと思うけれど
telldirもseekdirも機能しないんだから必要でも存在しない事実をどうする。 一旦readdirだかscandirでざっくりと読み込んで それに対して操作するしか方法が無いのが現実。 バックアップとかで完全一致を目指す場合 「ほぼあっている」前提ならば結局ファイル自体の完全マッチをするしかないと思うが 事前にMD5とかSHA1とかとったリストをディレクトリーに入れとけばそれで済む気はする。
|

|