檜山正幸のキマイラ飼育記 このページをアンテナに追加 RSSフィード Twitter

キマイラ・サイトは http://www.chimaira.org/です。
トラックバック/コメントは日付を気にせずにどうぞ。
連絡は hiyama{at}chimaira{dot}org へ。
蒸し返し歓迎!
このブログの更新は、Twitterアカウント @m_hiyama で通知されます。
Follow @m_hiyama
ところで、アーカイブってけっこう便利ですよ。

2008-09-30 (火)

OSが何でも、Perlスクリプトをコマンドとして気持ちよく起動する方法

| 13:18 | OSが何でも、Perlスクリプトをコマンドとして気持ちよく起動する方法を含むブックマーク

とある事情により、Windows、UNIX系OS、Windows上のMSYS(またはCygwin)の3つの環境で同一のスクリプトを動かしたいのです。最初、bashのシェルスクリプトを3つの環境で使おうと思っていたのですが、なかなかに難しい。それで、Perlにしようかと考え直しました。スクリプト言語は別になんでもいいのです。

さて、僕の要望は次の2つです。

  1. Perlソースファイルは環境によらず単一で、hello.plのような.pl拡張子を持つ。
  2. だが、コマンドラインから実行するときは、hello としたい。

1番目の.pl拡張子に関しては、エディタとかGUIシェルとか人間とかが、すぐにPerlスクリプトだと認識できて便利だからです。2番目のほうは単に気分の問題、合理的根拠は特にありません。コマンド名に拡張子が付くと気持ち悪くてイヤなのよー。

[追記]以下の方法は、Perl以外のスクリプト言語でも同じように適用できると思います。最後のシェルスクリプトは、古いのと新しいのが混じっていたので、修正しました。[/追記]

サンプル

hello.pl

#!/usr/bin/perl
print "Hello from Perl.\n";

Windows

WindowsではActivePerlを使うことにします。ActivePerlをインストールすると、.pl拡張子はPerlコマンドと関連付けられます。ファイルhello.plを、環境変数PATHに含まれるディレクトリに置けば、hello.pl(拡張子含める)で実行できます。拡張子なしでもいいようにするには環境変数PATHEXTに.PLを追加するだけです。

>hello.pl
Hello from Perl.

>hello
'hello' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。

>echo %PATHEXT%
.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH

>set PATHEXT=%PATHEXT%;.PL

>hello
Hello from Perl.

>

Unix系OS

hello.plを実行可能に設定し、helloという名前(拡張子なし)のシンボリックリンクを作成すればいいでしょう。

$ chmod +x hello.pl
$ ./hello.pl
Hello from Perl.
$ ./hello
-bash: ./hello: No such file or directory
$ ln -s hello.pl hello
$ ./hello
Hello from Perl.
$

MSYS(またはCygwin

MSYSでは、シンボリックリンクはうまく働きません(ファイルコピーがされてしまいます)。Cygwinでは、Windowsの.lnkファイルでシンボリックリンクを模倣しますが、これも問題があるので、シンボリックリンクの使用はあきらめます。

次のような、hello.plを起動するシェルスクリプトを作成しておくことにします。

#!/bin/sh
perl '/c/Documents and Settings/Hiyama/Work/bin/hello.pl' $*

作業の自動化

シンボリックリンクまたは起動シェルスクリプトを作る作業をシェルスクリプトにしてみました。

#!/bin/sh

if [ -z "$1" ]; then
 echo Usage: $0 command-file-name-to-create
 exit 0
fi

relative=`echo "$1" | sed -e 's@^/@@'`
if [ "$1" = "$relative" ]; then
 cmd_file="$PWD/$1"
else
 cmd_file="$1"
fi

if [ -e "$cmd_file" ]; then
 echo "file '$cmd_file' already exists."
 exit 1
fi
if [ ! -e "$cmd_file.pl" ]; then
 echo "file '$cmd_file.pl' does not exist."
 exit 1
fi

mingw=`uname | grep MINGW`
if [ -z $mingw ];then
 chmod +x "$cmd_file.pl"
 ln -s "$cmd_file.pl" "$cmd_file"
else
 echo '#!/bin/sh' > "$cmd_file"
 echo perl "'$cmd_file.pl'" '$*' >> "$cmd_file"
fi

リンク元