Koji Arai
JCA02****@nifty*****
2002年 12月 15日 (日) 23:12:28 JST
新井です。 In message "Re: [Lha-users] Ignore dot-files patch" on Sat, 14 Dec 2002 14:00:49 +0900, Hiroto Sakai <sakai****@fan*****> wrote: > 坂井です。 > > In Sat, 14 Dec 2002 06:56:40 +0900, Koji Arai wrote: > >> GNU tar の -X のように除外したいファイルを指定できれば > > っという方向にすべきでしょうか?(fnmatch(3) 使えばいいかな?) > > そう思います。 一応、実装してみました。(まだ CVS に commit してません)tar の -X はファイルに除外ファイル(パターン)をリストしてそのファ イルを指定するオプションなので、-x <pattern> にしました。(-x は、GNU diff にあるオプション)ちょっと eXtract と紛らわしい ですが。 また、明示的に圧縮対象のファイルとして指定した場合は、パター ンの方は無視されます。 つまり、 lha cx'*.o' src.lzh src/*.o とかだとすべての .o は圧縮されます。(意図してそうなったので はない^^;) > ただ、Windows エクスプローラーではドットファイルは > 作ることを許してくれないなど、あちらでもイレギュラーな > 存在なので、一律に無視するのもありかなあとも思います。 .始まりなファイルは隠しファイルだとみなして-x で、パターンを 書かない場合に . で始まるファイルを無視(つまり、-x のデフォ ルトパターンは、'.*')でもいいかもしれませんね。 Mac OS X での需要が高いのなら再度検討します。 > そういう意味では、毎回除外ファイルを指定するよりも > Windows で都合の悪い/使わなさそうなファイルを一括して > 無視してくれるオプションがあれば便利でよいですねえ ^_^; > もちろん、任意のファイルを除外する機能もあれば素敵です。 > # lha -a hoge.lzh --windows -X huyo.txt hoge みたいな? これはおそらくエクスプローラで扱えないファイルを無視するので はなく、DOSでファイル名として無効な文字を置換してあげる機能 の方が便利ではないかと思います。他にも文字の大小の違いだけの ファイルとか warning 出しつつ変えてあげるとか。 > MacLHA で MacBinary を指定した書庫でしか発生しないので > 需要はあまり無いと思います。そうやって作った書庫を活用するのは > きっと Mac ユーザですから MacLHA などで解凍するでしょうし。 > > Mac OS X 用に LHa for UNIX のフロントエンド(DropUnLHa)を > 作ったんですが、リクエストは今のところありません。 りょっかい。 以下、-x オプションのパッチ。まだ、autoconf とかは考慮されてません。 (GNU でない free な fnmatch() を探さなきゃ) realloc してる部分はとてもカッコ悪いのですが、lha のソースに 付属されたstring pool を使えばいいかなあっと思いつつ使い方を 調べてないので放置してます。 ま、仕様の方向性の検討が先ですから。 Index: src/lha.h =================================================================== RCS file: /cvsroot/lha/lha/src/lha.h,v retrieving revision 1.34 diff -u -u -p -r1.34 lha.h --- src/lha.h 24 Nov 2002 18:16:14 -0000 1.34 +++ src/lha.h 15 Dec 2002 13:54:18 -0000 @@ -141,6 +141,15 @@ int utime(const char *, struct utimbuf * # endif #endif +#if HAVE_FNMATCH_H +# include <fnmatch.h> +#else +int fnmatch(const char *pattern, const char *string, int flags); +# define FNM_PATHNAME 1 +# define FNM_NOESCAPE 2 +# define FNM_PERIOD 4 +#endif + #ifndef SEEK_SET #define SEEK_SET 0 #define SEEK_CUR 1 @@ -296,6 +305,7 @@ EXTERN boolean recover_archive_when_int EXTERN boolean remove_extracting_file_when_interrupt; EXTERN boolean get_filename_from_stdin; EXTERN boolean ignore_directory; +EXTERN char **exclude_files; EXTERN boolean verify_mode; /* Indicator flag */ Index: src/lharc.c =================================================================== RCS file: /cvsroot/lha/lha/src/lharc.c,v retrieving revision 1.54 diff -u -u -p -r1.54 lharc.c --- src/lharc.c 16 Nov 2002 19:03:23 -0000 1.54 +++ src/lharc.c 15 Dec 2002 13:54:18 -0000 @@ -90,6 +90,7 @@ init_variable() /* Added N.Watazaki remove_extracting_file_when_interrupt = FALSE; get_filename_from_stdin = FALSE; ignore_directory = FALSE; + exclude_files = NULL; verify_mode = FALSE; noconvertcase = FALSE; @@ -147,6 +148,7 @@ commands: opti c re-Construct new archive w=<dir> specify extract directory (a/u/m/x/e)\n\ p Print to STDOUT from archive d delete FILES after (a/u/c)\n\ t Test file CRC in archive i ignore directory path (x/e)\n\ + x=<pattern> eXclude files (a/u)\n\ z files not compress (a/u)\n\ g Generic format (for compatibility)\n\ or not convert case when extracting\n\ @@ -336,6 +338,23 @@ main(argc, argv) case 'i': ignore_directory = TRUE; break; + case 'x': + if (*p == '=') + p++; + if (!exclude_files) { + exclude_files = (char**)xmalloc(sizeof(char*) * 1); + exclude_files[0] = 0; + } + + for (i = 0; exclude_files[i]; i++) + ; + exclude_files = (char**)xrealloc(exclude_files, + sizeof(char*) * (i+1)); + exclude_files[i] = xstrdup(p); + exclude_files[i+1] = 0; + + p += strlen(p); + break; case 'w': if (*p == '=') p++; @@ -844,7 +863,7 @@ find_files(name, v_filec, v_filev) { struct string_pool sp; char newname[FILENAME_LENGTH]; - int len, n; + int len, n, i; DIR *dirp; struct dirent *dp; struct stat tmp_stbuf, arc_stbuf, fil_stbuf; @@ -864,6 +883,12 @@ find_files(name, v_filec, v_filev) GETSTAT(archive_name, &arc_stbuf); for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) { + for (i = 0; exclude_files && exclude_files[i]; i++) { + if (fnmatch(exclude_files[i], dp->d_name, + FNM_PATHNAME|FNM_NOESCAPE|FNM_PERIOD) == 0) + goto next; + } + n = NAMLEN(dp); strncpy(newname + len, dp->d_name, n); newname[len + n] = '\0'; @@ -890,6 +915,7 @@ find_files(name, v_filec, v_filev) add_sp(&sp, newname, len + n + 1); } #endif + next: } closedir(dirp); finish_sp(&sp, v_filec, v_filev);