GNU toolsのWindows版GnuWin32を使う
WindowsでUNIXライクな環境といえばCygwinやMinGW/MSYSがあるわけだけど、そこまでは必要ない、ちょっとコマンドが使えればいいだけ、という場合にはGnuWin32がお手軽で便利。おすすめ。もう後の文は読まなくていいから黙って入れちゃえよ!
GnuWin32
GnuWin32
http://gnuwin32.sourceforge.net/
GnuWin32 provides ports of tools with a GNU or similar open source license, to MS-Windows (Microsoft Windows 95 / 98 / ME / NT / 2000 / XP / 2003 / Vista / 2008)
GnuWin32は上記のように書かれているとおりGNU toolsをWindowsに移植したコマンド群。
それぞれのパッケージ毎にダウンロードして展開すればコマンドプロンプト上ですぐに使える。
インストーラ型をぽちぽち入れていくのは面倒なのでzipをダウンロードしてまとめて展開したほうが楽だと思う。
その際はBinariesの他にDependenciesも忘れないように。
まとめてインストール
トップページのメニューにあるDownload allにはまとめて全部ダウンロードしてインストールしてくれるサポートツールが紹介されているのでこれを利用するとだいぶ楽。
なのだが、微妙にうまく動いてくれなくて、いくつか抜けたり古いバージョンを落としてきたりするので修正しようと思ったんだけど、バッチファイルが難解すぎて理解できなかったのでperlでダウンロードスクリプトを書いてみた。
getgnuwin32.pl
Strawberry Perl v5.10.0.4で動作確認済み。Strawberry Perlについては昔のエントリを参照。
Web::ScraperとかPath::Classを使ってるのでcpanコマンドで別途入れる必要がある。正規表現でがりがりパースする気力はなかった……。
誰か標準モジュールだけで動くように書き換えてくれると嬉しい。
で、これを実行するとpackagesというディレクトリに各パッケージのzipがひたすらダウンロードされるので、終わったらC:\gnuwin32とかに全部展開すればいいんじゃないかな!
getgnuwin32.lstってのは上記の一括インストーラが使うのと同じ形式のリストファイル。特に意味はない。
※2009年5月30日修正:ダウンロードできなくなってた。
use utf8; use strict; use warnings; use URI; use Web::Scraper; use LWP::UserAgent; use HTTP::Request::Common; use Path::Class::File; use IO::File; my $GNUWIN32_LIST = 'http://sourceforge.net/project/showfiles.php?group_id=23617'; my $GETGNUWIN32_FILE = 'getgnuwin32.lst'; my $FILELIST_FILE = 'filelist.txt'; my $PACKAGES_DIR = 'packages'; # get package list my $commands = scraper { process '.yui-b>table>tbody>tr', 'commands[]' => scraper { process '/tr/td[1]/a', 'name' => 'TEXT'; process '/tr/td[2]/a', 'url' => '@href'; }; result 'commands'; }->scrape(URI->new($GNUWIN32_LIST)); mkdir $PACKAGES_DIR if (!-e $PACKAGES_DIR); my $getlist = IO::File->new($GETGNUWIN32_FILE, 'w') || die $!; my $filelist = IO::File->new($FILELIST_FILE, 'w') || die $!; my $ua = LWP::UserAgent->new; # download packages eval { for my $cmd (@$commands) { # skip document-only package next if ($cmd->{name} =~ /-doc$/); # get zip filename and download url my $zips = scraper { process '//tbody[@id="pkg0_1"]/tr[starts-with(@id, "pkg0_1rel0_")]/td[2]/a', 'zips[]' => { name => 'TEXT', url => sub { my $url = $_->attr('onclick'); $url = $1 if ($url =~ /init_download\('([^']+)'\)/); $url; }, }; result 'zips'; }->scrape($cmd->{url}); print "package $cmd->{name}\n"; $getlist->print(" $cmd->{name}\n"); for my $zip (@$zips) { # print $zip->{name} . ': ' . $zip->{url} . "\n"; # only bin, dep, lib, doc if ($zip->{name} =~ /(?:bin|dep|doc|lib)\.zip$/) { $getlist->print("$zip->{name}\n"); $filelist->print("$zip->{name}\n"); my $zip_file = Path::Class::File->new($PACKAGES_DIR, $zip->{name}); if (-f $zip_file) { print " $zip->{name} is exist. download skipped.\n"; } else { print " download $zip->{name}\n"; my $retry = 3; while ($retry-- > 0) { my $res = $ua->request(GET $zip->{url}); if ($res->is_success) { my $fh = $zip_file->openw(); $fh->binmode(); $fh->print($res->decoded_content); $fh->close; last; } else { print " failed... " . $res->status_line . "\n"; } } } } } } }; if ($@) { print STDERR $@; } $getlist->close; $filelist->close;
※sourceforge.netのページをパースしているので、デザインが変わったりすると動かなくなるかもしれないけど、そのときはパッチを送ってくれるといいと思うよ!
配置とパス
例えばC:\gnuwin32に展開したとするとこんな感じになる。
C:\gnuwin32 |-- bin |-- contrib |-- doc |-- etc |-- include |-- info |-- lib |-- libexec |-- man |-- manifest |-- misc |-- sbin |-- share `-- var
libとかshareもbinと同列の配置でうまく参照してくれる。
で、早速C:\GNU\binをPATHに加えたくなるわけだが、正直おすすめしない。
とういのもWindows標準のコマンドと一部(findとかsortとか)がかぶるので、これらを使ってるプログラムやバッチファイルが誤動作して痛い目に遭う可能性がある。