Win32 Command shell MicroShell dash Version 1.21 1998 02/20 小笠原博之 オリジナルのコマンドシェルです。Windows の DOSプロンプト上で使用することが できます。UNIX 風コマンド、ヒストリ、ファイル名補完等、最小限の機能を内蔵し、 シェル関数定義可能なスクリプトプログラミングも可能です。 もともとは、必要最小限かつコンパクトな起動システムを構築する目的で 1993年に X68000 の Human68k 上で開発されたものです。X68000 版 v1.16 をベースに、Win32 に移植しました。開発と動作確認は Windows95 でのみ行っています。 ●導入方法 アーカイブには以下のファイルが含まれています。 dash.txt マニュアル dash.exe プログラム本体 dashinit.rc 設定ファイルサンプル more.exe more コマンド dsah.exe, more.exe を、パスの通った適当なディレクトリにコピーしてください。 また dashinit.rc も、dash.exe と同じディレクトリに入れておいてください。 explorer から dash.exe をダブルクリックするか、DOS プロンプトを開いて dash コマンドを実行してください。コマンドシェル dash が起動します。 あとは通常の DOS プロンプト同様に、コマンドをキータイプして [RETURN] キーを 押すとプログラムが実行されます。 (例) dash> ls dash> notepad & ウィンドウプログラムなど、並列実行させる場合は最後に & をつけます。もちろん、 コンソール用コマンドも & によって並列実行可能です。 dash> nmake & dash> exit シェルを終了するには exit コマンドを入力してください。 ※「dash>」はシェルプロンプトの説明用の表現です。実際は「%」もしくは「ディレ クトリ名>」になります。プロンプトは自由に定義できます。 ● DOS プロンプトのショートカットに dash を直接登録するには 必要に応じて設定してみてください。dash を一発で起動できるショートカットの作 成方法です。 Windows がインストールされているディレクトリ (dash 上で echo $WINDOWSDIR と 実行すると表示される) にある、COMMAND.COM のショートカットを作成してください。 そのショートカットアイコンの上で右ボタンのプロパティを開きます。プログラム のタブのコマンドラインのところを、dash.exe をインストールしたディレクトリへの フルパスにしてください。また作業ディレクトリは、dashinit.rc を置いたディレク トリに変更してください。 <例> コマンドライン c:\app\bin\dash.exe 作業ディレクトリ c:\app\bin あとは、ショートカットアイコンの名前を dash に変更すれば完成。このアイコン をダブルクリックすれば、COMMAND.COM を介さないで直接 dash が起動するようにな ります。 ●起動方法詳細 dash [-f] [-c] [] シェルプログラムです。COMMAND.COM 同様、コマンド名のキータイプによりプログ ラムの実行を行います。コンソールを使用するので、DOSプロンプト上で実行してくだ さい。 -f スイッチがある場合、初期化コマンド($DASHINIT)の実行を行いません。-c ス イッチは特に意味を持ちません。無視します。引数の順番は固定です 引数に を指定した場合は、そのコマンドの実行が終わるとすぐシェルは 終了します。 ●行置換 行内に置かれた以下の文字は特殊な意味をもち、実行前に以下のような置換が行わ れます。 ~ 環境変数 HOME の内容に置換します。 \ 後ろの特殊文字をそのまま出力します。 (例) \\ → \ \$ → $ \cN 特殊コードに置き替わります。 (例) \cA → CTRL+A \c[ → ESC \cM\cJ → CR LF (改行) "〜" スペース等を含む文字列を与えます。 '〜' 文字列の変換を一切行わない場合シングルクオートで囲みます。 `〜` 行置換中にプログラムを実行します。ただし、まだ表示出力は取り 込みできません。 ファイル名展開はありません。このシェルではパスの区切りは '/' でも '\' でも どちらでも構いませんが、上記のように '\' は特殊扱いされるため '\\' と2重に して記述する必要があります。これを忘れるとトラブルの元になりますので、できる だけ '/' で記述するようにして下さい。 注: dash の行置換のエスケープ実装は不完全です ●行の区切り ; cmd1 ; cmd2 の場合、両方を順番に実行します。ただし、行として は1つとみなすため行置換は一括して行われます。(あまり使うべき ではないかもしれない) & バックグラウンド実行の指定です。; 同様コマンドの区切りとして 働きますが、コマンドの終了を待たずに次の処理を行います。例え ば cmd1 & cmd2 の場合、2つのコマンドは同時に実行されます。 ウィンドウを開くアプリケーションの場合でも、UNIX+X-window の ように最後に & をつけないとプロンプトが戻ってこないので注意 してください。 <例> notepad & | パイプ指定です。& 同様コマンドの区切りでさらに並列実行を行い ます。この時、プロセスの標準出力を次のコマンドの標準入力とし て扱います。 <例> ls -l | more 注意: パイプはプロセスの並列実行で行なわれるため、32bit アプ リケーション以外では使えません。例にある more コマンド は、32bit 版を付属しています。 # 以後行末まで無視します。コメント ●変数置換 $ で始まるシンボルは、環境変数の内容に置換されます。以下のようにさまざまな 文字操作を伴わせることができます。変数名の大文字小文字は区別します。 $var 環境変数 var の内容に置換。変数名の分離のため ${var} という指 定が可能です。 ${var#str} 変数 var の内容が str で始まる場合その部分を取り除いた文字列 になります。 ${var%str} 変数 var の内容が str で終わる場合その部分を取り除いた文字列 になります。 (例)set VAR=test.c の時 echo ${VAR%.c} とすると「test」になる ${var-str} 変数 var が定義されていればその内容、変数が定義されていなけれ ば str に置き替わります。 (例) ${home-$HOME} 変数homeが定義されていなければHOMEの内容 ${var+str} 変数 var が定義されていれば str、定義されていなければ NULL に 置き替わります。 ${var=str} 変数 var が定義されていればその内容、変数が定義されていない時 str の内容に置換し、さらに変数 var に str をセットします。 ${var:str} str の文字によって、変数 var の内容を変換します。 ? 文字数 u 大文字変換 l 小文字変換 / パスの区切りを'/'に変換 \ パスの区切りを'\'に変換 r パスの進路名部分 n パスのファイル名部分(拡張子含む) e パスの拡張子部分(1番最後のもの) f パスの拡張子(1番最後のもの)を除いた部分 p 変換内容を表示 q 無条件に内容を捨てる h 内容を数値として16進数8文字に置換 s 内容を文字コードとして文字に置換 d 内容の先頭文字のコードに置換 wn n番目のワード(再変換あり) cn n文字目以降 tn 先頭のn文字 (例) ${HOME:/l} パスの区切りを全部'/'にしてかつ小文字にする str の部分は再変換の対象となるため、さらに $var 等の指定ができます。({}の ネストはできない) ●シェルで参照する変数 DASHINIT 初期化コマンド。起動時にこの変数内の文字列を実行します。定義 されていなければ「. dashinit.rc」を実行します(つまり、カレン トディレクトリの dashinit.rc というファイルを実行する)。-f ス イッチをつけた場合は実行しません。 PS1 プロンプト文字列 (定義されていない場合は '%' ) 出力時に行置換 の対象となります。 (例) set 'PS1=${PWD:\\}\>' プロンプトにカレントディレクトリ内容を入れる、COMMAND.COM の 「PROMPT $P$G」相当 HOME cd コマンドで引数を指定しない場合、この変数で設定されたディ レクトリに移動します。 ●システム変数 読み出しのみ可能。ユーザーからの定義はできません。また、set コマンドで表示 する一覧にも含まれません。 ? 直前のコマンドの終了コード / repeat 実行時のカウント値 0〜9 引数並び (. や source コマンド実行時または function 定義され た関数実行時, $0 はコマンド名) < 1行入力待ちをし、入力した文字列に置き替わります。(この入力待 ちの間もヒストリやファイル名補完が可能) * @ $0 を除く引数並び全部に置き替わります。どちらも "$1 .. " と処 理されることに注意して下さい。(本来なら、$@ は異なるべき)分割 するには eval が必要です。 PWD カレントディレクトリの内容です。 RANDOM 乱数値を持ちます。 GETKEY キー入力待ちをし、1文字キー入力を行います。押されたキーのコー ド(数値)になります。 GETKEY0 キーバッファの最初の1文字を参照します。入力がない場合は 0 に なります。 GETKEY1 リアルタイムキー入力をします。入力がない場合は 0 です。 VERSION シェルのバージョン文字列が入ります。 SYSVER システムのバージョンを説明する文字列が入ります。 HOSTNAME コンピュータ名が入ります。 USERNAME Windowsのログインユーザー名が入ります。 SYSTEMDIR Windowsのシステムディレクトリが入ります。 WINDOWSDIR Windowsがインストールされているディレクトリが入ります。 <例> キーコードを調べる場合 dash> echo $GETKEY この後押したキーのコードが表示される。 ●リダイレクト > file 標準出力の切り替え >> file 標準出力のfile追加切り替え >e file 標準エラー出力の切り替え >>e file 標準エラー出力のfile追加切り替え < file 標準入力の切り替え | command 標準出力を command の標準入力として実行(パイプ) 内部コマンドのリダイレクトを行った時は、サブシェル呼び出しが行われることに 注意して下さい。 'e' で始まるファイル名をリダイレクトするときは、必ず '>' や '>>' とファイル 名を離して記述して下さい。 ●内部コマンド []内部は省略可能なことを意味します。.. とある部分は同一の引数を繰り返し指 定が可能です。コマンドの大文字小文字は明確に区別します。 and その時点での終了コードが 0 の時 cmd を実行し、0 でなければ終 了コード 1 を返します。or コマンドとともに、if 文の条件式結合 に使用できます。 (例) if [ $A = NO ];and [ $B = NO ]; then .. また、単体でも簡単な if 構文を構築できます。 (例) [ $A = NO ];and ls これは「 if [ $A = NO ];then ls ; fi 」に相当します。つまり、 perl でいう「&&」のことです。 cat .. 極々簡単なファイルの表示コマンドです。ワイルドカード展開しま す。UNIX 等の改行コードが LF (0x0a, \n) だけのファイルも表示 できるようにしてあるため、このコマンドでバイナリファイルの連 結はできません。UNIX から持ってきた改行が LF だけのファイル を改行 CR LF (0x0d 0x0a, \r\n)に変換したいなら、このコマンド の出力をリダイレクトしてファイルに保存するだけで OK です。 注: 行単位で処理している関係上、行があまりに長いファイルの場 合は表示の時行が途中で切られている場合があります。 cd [] ディレクトリ,ドライブ移動。親ディレクトリは「..」で、「.」を 増やすたびにさらに親ディレクトリに移動します。例えば cd ... の場合は、二つ上の親に移動します。 ディレクトリ名を省略すると環境変数 HOME のディレクトリに移動 します。もし ksh のような OLDPWD を使いたいなら function cd { set "OLDPWD=$PWD" =cd ${1-~} } と再定義すればいいでしょう。 chmod [-R] {+-} .. .. ファイルのモードを変換します。+ でモード追加、- で削除です。 ワイルドカード展開が可能で、-R をつけるとディレクトリ以下も 再帰的に全ファイルの変換をします。 mode r 読み出し属性 h 不可視属性 s システム属性 (例) chmod +hr file cp cp .. ファイルを複製します。ディレクトリ名に対してコピーする場合に のみ複数ファイル名が指定できます。ワイルドカード展開します。 ctrlkey .. 行入力中のコントロールキーの機能をそれぞれ設定します。code は 割り付けるコントロールキーの 1〜31 (CTRL+A〜CTRL+_) のコード を直接与えます。fnc は数値で、以下の通り。 fnc 名前 意味 0 NOP 何もしません 1 ENTER リターンキーです 2 ERASE 1文字消去します BS のこと 3 FCOMP ファイル名補完します 4 GENV 環境変数 _ の内容取り込み 17 HISTP ヒストリをさかのぼります 18 HISTN ヒストリを戻ります 32 RDRAW バッファ内を再描画します 64 KILL バッファを全部消去します 128 EXEC 直接プログラムを呼び出します KILL, EXEC, RDRAW は、他の機能に対して値を加算して、複数の機 能を持たせることができます。(例 KILL+GENV=68) (例) CTRL+B をリターンキーと同じ働きにする ctrlkey 2 1 (例) ESC でファイル名補完できるようにする ctrlkey 27 3 (例) ヒストリ移動を CTRL+E と CTRL+X (ED.Xバインド)にする ctrlkey 5 17 24 18 EXEC を指定した場合、c数値 というコマンドを直接実行しようと します。例えば ctrlkey 12 160 (160=EXEC+RDRAW)と実行すると、 CTRL+L を押した時に c12 というコマンドを直接実行します。これ を利用して、 function c12 'echo -n "\c[[2J"' のようにでも定義しておけば、CTRL+L を押すとすぐ画面を全消去 するようになります。なお、この時入力中のバッファの文字列は保 存されます。もし、CTRL+L の時に入力バッファの内容もクリアし たければ、ctrlkey 12 224 (EXEC+RDRAW+KILL)としておけばいいで しょう。 もちろん、よく使うコマンドを直接起動するためにこの EXEC 機能 を使うことができます。例えば、 ctrlkey 1 224 function c1 'ls -l' のように定義すれば、いつでも CTRL+A を押せば ls -l を実行す ることになります。同様に、 ctrlkey 11 160 function c11 'ls -a' というのもいろいろ使い道があるかもしれません。これは行入力の 途中であっても、CTRL+K を押すだけでそのディレクトリの内容を 見ることができます。 さらに、EXEC で呼び出した c数値 というプログラムには、その時 の行バッファの文字列が引数として与えられるため、 ctrlkey 5 160 function c5 'notepad $@ &' のように定義すれば、最初にファイル名を書いて、その後 CTRL+E を押すだけでいきなりエディタが起動します。 ctrlkey 1 160 function c1 'eval "ls -l $@"' というのも非常に興味深い設定です。これは行入力途中のファイル 名の、タイムスタンプやファイルサイズ等を、行入力途中で参照で きるというものです。 などなど、他にも ksh のように環境変数 _ を設定してみたり、関 数定義によって行内の編集コマンドを拡張するなど、いくらでも応 用がきくでしょう。 (例) CTRL+A で行バッファ内の文字を先頭から1文字ずつ消す ctrlkey 1 196 function c1 'set "_=${@:c1}"' (例) CTRL+A で行バッファ内のアルファベットを大文字にする ctrlkey 1 196 function c1 'set "_=${@:u}"' df [] 各ドライブのディスク容量を表示します。ドライブ名を与えるとそ のドライブについてだけ表示します。 (実行例) Filesystem kbytes used avail capacity Mounted on A:/removable C:/fixed 2056256 1686144 370112 82% C:/ ( 64/512) D:/fixed 830336 482256 348080 58% D:/ ( 32/512) E:/fixed 830336 490352 339984 59% E:/ ( 32/512) F:/fixed 838400 837744 656 99% F:/ ( 32/512) O:/removable 122622 96582 26040 78% O:/ ( 4/512) R:/cd-rom 572928 572928 0 100% R:/ ( 16/2048) S:/cd-rom 左から、ドライブ名と種類、全容量、使用容量、残り容量、割合、 進路名への割りあてとなります。(圧縮ドライブの場合は正しい値に ならないことがあります) du [-s] [] .. そのディレクトリの消費しているディスク容量を求めます。表示単 位は Kbyte です。サブディレクトリ以下をたどって、ファイルサイ ズの合計をディレクトリ毎に報告します。ただし、ディレクトリ自 身はブロックサイズの合計に含まれないことに注意して下さい。 -s スイッチをつけた場合は、途中のディレクトリでのサイズ表示を 行わず、常に合計のみ表示します。 echo [-n] [] .. 文字列表示です。-n スイッチをつけた場合は最後に改行をつけま せん。各要素は単一のスペースで区切ります。 eval .. cmd を再評価したのち実行します。いちばん最後に実行したコマン ドの終了コードを返します。C言語の「,」のようなもの。 exit [] 自分自身のシェルの終了。終了コードを省略した場合は 0 です。 set コマンドでオプションフラグの 2 が設定されている場合は、こ のコマンドの実行は失敗します。 exec .. cmd を常に外部コマンドとして実行します。UNIX シェルの exec と は異なり、cmd の実行が終わると元の場所に戻ってきて続きを実行 します。 export .. 環境変数登録。set と export は全く同じ命令です。一度に複数指 定できます。引数のクオートは、変数名を一緒に行うことに注意し て下さい。=の両端にスペースを含んではいけません。 (例) set TEMP=d:/home 'PS1=$PWD\>' export 設定されている環境変数一覧を表示します。 export 内部のフラグレジスタを設定できます。現在有効なものは次の通り です。デフォルトは 32 です。 bit1( 2) exit コマンド等シェルの終了を禁止します bit2( 4) 外部コマンド実行時の実行行をエコーバックします bit5(32) 内部コマンド実行時の実行内容を報告します (例) set 36 すべてのエコーをON set 0 コマンド行エコーをすべてOFF function function { .. } 関数定義です。内部コマンドを登録します。定義したコマンドの扱 いは source 実行時とほぼ同じで、引数も $@ や $1〜9 等を展開し ます。異なるのはメモリ上に置かれることだけです。実行は制御文 を除いた内部コマンドに常に優先され、このシェルにおける alias 代わりにも働きます。ブロック指定の「{」「}」は必ず独立行にな ければなりません。1行で指定できる簡単な関数は、ブロックを指 定しないで名前の直後にコマンド行を書くことができます。この場 合必ず「'」でクォートが必要。 例えば、function 自身で csh の alias のようなコマンドを作るに は、次のようにします。( { と } はネストできません ) function alias { shift if [ "$1" ];then function $0 "$@ \$@" fi } 以後「alias rd rmdir」のように定義できるようになります。 function 定義されている関数の定義内容一覧を表示します。 if ; then ; [elif ; then ;..] [else ;] fi cmd1 の終了コードが 0 の場合、then 以後の cmd2 を実行、0 以外 の場合、else 以後の cmd を実行します。もし elif があるなら、 else ではなく再びそこで終了コード評価します。実行されない部分 も行の評価は行われるので、副作用を持つ行置換には注意。 cmd1 (cmd4) 部分は、たいてい test コマンド([)が用いられます。 (例) if [ "$VAR" = "SET" ];then .. fi この例では、test コマンドによって変数 VAR の内容と SET とい う文字列を比較し、その結果が成り立てばブロック内を実行します。 test コマンド '[' の前後には、必ずスペースが必要です。同様に ']' の前にもスペースが必要です。if ブロックは多段階にネスト できます。 lfor [-R] .. : eval 変数 name に随時 str を代入しながら cmd を実行します。str の ワイルドカード文字列はファイル名に展開します。-R を付けると、 ディレクトリ以下、再帰的に展開します。つまり for というより、 ほとんど find . -exec になります。lfor のネスティングはできま せん。(lwhile, repeat では可能) (例) lfor name *.c : eval 'echo $name' ls [-la] [] .. 簡単な ls コマンドです。ディレクトリ内容をリストします。ファ イル名を指定すると指定ファイルだけ表示します。ファイル名のソー トは行いません。ワイルドカードが使えます。-l スイッチをつけた 場合、他の情報も一緒に表示します(ファイルアトリビュート、ファ イルサイズ、タイムスタンプ)。-a スイッチをつけると . で始まる ファイル、不可視属性やシステムファイル、ボリュームラベルも表 示するようになります。-l と -a を同時に指定する時は、-la のよ うにくっつけて下さい。(-alでも可) (実行例) ls *.c microshell.c print.c line.c exec.c inner.c cmd.c env.c ai_fio.c string.c if.c expr.c stest.c alias.c rm.c history.c ps.c more.c cp.c df.c ls.c (実行例) ls -l *.doc a----- 23658 1993-08-05 0:53:08 dash.doc a----- 5260 1993-08-01 22:47:42 aish.doc a----- 3035 1993-06-15 10:51:30 koishenc.doc (例) 最初にそのドライブの容量も表示する場合 df $PWD;ls -l (例) ディレクトリ以下もファイル全部表示する場合 lfor -R name * : eval 'ls -l $name' -F オプションはありませんが、ディレクトリの場合はファイル名 の後ろに常に '/' を付けます。 ディレクトリ名を与えてもそのディレクトリ以下のファイル名は表 示しません。ディレクトリ名もファイルの1つとして情報を表示し ます。(ディレクトリ内のファイル表示をする場合は /* をつける) lwhile cmd の終了コードが 0 の間、cmd を繰り返し実行します。cmd は1 コマンドだけなので eval と組み合わせて簡単な while 文が作れ るでしょう。 (例) lwhile eval 'echo $1' shift mkdir .. ディレクトリを作成します。一度に複数指定可能です。 more [] ファイルの内容を表示します。この時、ページ単位で停止し、キー 入力待ちを行います。ファイル名を省略すると、標準入力から読み 込みます。 このコマンドは、フィルタとして使われる用途が多いことから、シェ ル組み込みではなく外部コマンドになっています。DOS の more コ マンドが .com であり、dash のパス検索に引っかからない対策用 でもあります。機能は最小限なので、もし、他の more.exe を使用 しているならそちらでもかまいません。 停止時のキー操作 [SPACE] 次のページ [ENTER] 1行送り [ESC]/[Q] 停止 mv mv .. ファイルの移動、または名前変更を行います。相手先がディレクト リの時だけ複数ファイル指定が可能です。ワイルドカード展開しま す。同一のドライブ内でのみ可能です。 or その時点での終了コードが 0 でないとき cmd を実行し、0 ならば 終了コード 0 を返します。and コマンド同様、if 文の条件式結合 に使用できます。 (例) if [ $A = NO ];or [ $A = no ]; then .. また、単体でも簡単な if 構文を構築できます。 (例) [ $A = NO ];or ls これは「 if [ $A != NO ];then ls ; fi 」に相当します。つまり、 perl でいう「||」のことです。 repeat ごく簡単なループ実行を行います。cmd が count 回だけ実行され ます。複数命令は記述できないので、その場合は eval 等を使用し て下さい。eval 時のみカウンタを $/ で参照可能です。 (例) repeat 10 eval 'echo $/' rm [-r] .. ファイルを削除します。ワイルドカード指定が可能です。-r をつ けるとディレクトリ以下再帰的に削除します。 rmdir .. ディレクトリを削除します。一度に複数指定可能。ワイルドカード 指定が可能です。 set [] .. export と同じです。 shift 引数並びのパラメータを1つずらします。$0 も変化します。 source [..] テキストファイルの内容を、そのシェルで実行します。ファイル名 のあとに、引数並びを書くことができます。サブシェル呼び出しで はありません。source 中にファイル内でさらに source を実行し て別のファイルを呼び出すことができます。COMMAND.COM の .BAT とは違い、終了すると呼び出し元に復帰します。. と source は同 一です。 test [-] test さまざまなテストを行います。条件が成立すれば終了コード 0 を 返します。test と [ (省略の意味ではない) は同じ。主に、if 文 の条件コマンドとして実行されます。 cmd -r file ファイルが存在する -f file 通常のファイル -w file ファイルが書き込み可能 -d file ディレクトリである -z str 文字列の長さが0 -n str 文字列の長さが0でない -D drv そのドライブが使用可能かどうか調べる op str = str 文字列が等しい str != str 文字列が等しくない num -eq num 数値比較で等しい num -ne num 数値比較で等しくない num -gt num 数値比較 > num -ge num 数値比較 >= num -lt num 数値比較 < num -le num 数値比較 <= 単純な比較文展開だけで、-a や -o による結合はできません。つま り行の演算評価を行っているわけではありません。その点で setexpr による数値比較と異なります。条件の結合には and や or コマンド を使って下さい。(numの部分はexpr展開します) true [] 終了コード 0 を返します。引数で num を与えた場合はそれが終了 コードになります。これを利用して、false コマンドは次のように 定義できます。 function false 'true 1' ちなみに終了ステータスを反転するには、test コマンドを用いて function not 'test $? != 0' と定義できます。 unfunc .. 定義した関数を削除します。 unset .. 環境変数を取り消します。一度に複数指定可能です。 @ .. 環境変数に対して数式の演算結果を代入します。1つの式にスペース が入る場合、演算記号が特殊な意味を持つ場合はクォートが必要。 set 同様クォートは変数名をも含むことに注意して下さい。 使用可能な演算子 + 加算 - 減算 * 乗算 / 除算 % 余り & 論理積 | 論理和 ^ 排他的論理和 = 等しい == 等しい = と同じです != 等しくない > 大きい < 小さい >= 大きいまたは等しい <= 小さいまたは等しい 条件式は、成り立てば1、成り立たなければ0の値を取ります。比較 や演算は符号付きで行われますが、負数を扱うことはできません。 演算の優先順位は次の通りです。 「*,/,%」 > 「+,-」 > 「>,<,=,==,>=,<=,!=」 > 「&,|,^」 優先順位の変更に括弧「()」が使用可能。 expr コマンドを作るには、 function expr { @ "_=$1" echo $_ } のようにします。コマンドライン中でちょっと計算がしたくなった ら、「expr "17404*3"」等のように実行できます。 : [] 何もしない nop コマンドです。ただし行置換のみ行われます。(変 換結果は捨てられる)これを利用して、例えば「: ${HOME=a:/}」の ように実行すると、環境変数 HOME が未定義の場合 HOME に a:/ を 定義します。 . source と同じです。 [ [-] ] [ ] test と同じです。省略の [ と重なってややこしいのですが、「[」 がコマンド名です。最後の ] は無視します。 上記のコマンド名の最初に「=」をつけて実行させることもできます。これを利用し て、同名の関数が定義してある場合に内部コマンドを呼び出しできます。(例 =cd) mv、rm 等の組み込みコマンドは、ファイルにワイルドカード '*' 1文字を指定し た場合 '*.*' に変換します。 ●コマンドの検索順番 実行するコマンドは、以下の順で検索が行われます。 (1) if, then, else, elif, fi の制御コマンド (2) function で定義された内部関数 (3) その他の内部コマンド (4) 外部コマンド (拡張子がなければ .EXE とみなす) ● COMMAND.COM の内部コマンドについて dir 等のコマンドは、COMMAND.COM の内部コマンドなのでそのままでは実行できま せん。この場合は「COMMAND.COM /C コマンド名」の書式で指定する必要があります。 <例> dash> COMMAND.COM /C dir 多用する場合は function で定義しておいてください。 <例> function dir 'command.com /c dir $@' DOS の外部コマンドの場合は、いちいち COMMAND.COM /C をつけなくても、そのまま コマンド名だけで実行することができます。 <例> dash> start . ●行編集 行入力は、最小限の編集操作ができます。デフォルトで以下のキーが使えるように 設定されています(カッコの中のキーでも構わない)。これらのキーバインドは全部自 由に追加変更できます。 CTRL+U 入力バッファ全消去(KILL) CTRL+H ([BS]) 直前の1文字消去(ERASE) CTRL+I ([TAB]) ファイル名補完(FCOMP) CTRL+P (CTRL+W) ヒストリをさかのぼる(HISTP) CTRL+N (CTRL+E) さかのぼったヒストリを戻る(HISTN) カーソル移動による行編集はできません。コントロールコードの直接入力はできませ ん。行操作には 0x08 (BS) のみ使われているので、ほとんどどの端末でも操作可能で す。 以下の例では、全部デフォルトのキーバインドを想定して説明してあります。 ・ファイル名補完例 (下線部分がキー入力) その1 dash> vi dashi[TAB] → dash> vi dashinit.rc ~~~~~~~~~~~~~ ファイル名を途中まで入力したあと TAB を押すと、マッチするファイル名に置き替 わります。 その2 dash> vi *.x[TAB] → dash> vi dash.x ~~~~~~~~~~~ ファイル名をワイルドカードで指定して TAB を押すと、ワイルドカード部分を展開 します。漢字のファイル名など、入力が面倒な場合に、拡張子だけで補完させると大 変便利です。 候補が複数ある場合は、TAB を押すたびに切り替ります。 ・ヒストリ例 dash> vi[CTRL]+[P] → dash> vi dashinit.rc ~~~~~~~~~~~~ CTRL+P と CTRL+N で、過去に入力した行を呼び出すことができます。この例では、 過去に入力した「vi」で始まる行を検索呼び出しています。 ●関数領域 内部コマンド登録のための関数領域は、最初に起動された場合だけ 4Kbyte 確保し ます。これは -e スイッチの有無に関係なく、チャイルドで呼び出した場合でも常に 同一の領域が参照されるため、親で定義したコマンドは再登録することなく共通に実 行できます。(スレッドが異なる場合は別領域になります) ●ヒストリ領域 行数制限はなく、最大 1024 文字まで保存可能です。ヒストリ領域も関数領域同様 に共通化されるので、チャイルドで実行したコマンド行を、親に戻ってからヒストリ 参照することもできます。 ●コントロールキーバインド情報 ctrlkey コマンドによる、コントロールキーバインド情報も、関数やヒストリ同様 共通化されます。(32byte) ●初期化ファイル 起動時、もし環境変数 DASHINIT が定義されていなければカレントディレクトリの dashinit.rc を読み込み実行(source)します。もし DASHINIT が定義されていれば、 その定義内容を実行します。(内部で「${DASHINIT-.\ dashinit.rc}」を実行してい る) もし他ファイルを読ませたい場合は、DASHINIT に「. path」のように source コ マンドで定義しておきます。 COMMAND.COM の AUTOEXEC.BAT のように起動時にだけ初期化ファイルを読ませたい、 という場合なら、直接この dashinit.rc を編集するだけで OK です。2度目以降の起 動で間違って dashinit.rc を読まないようにするなら、dashinit.rc 自身で環境変数 DASHINIT に nop コマンドで書き込んでおいて下さい。(例) set 'DASHINIT=:' もし UNIX シェルのようにユーザー個別の初期化ファイルを実行させたいなら、シ ステムの起動ディレクトリに dashinit.rc を置き、そのファイルでデフォルトの設定 を行った後、HOME 毎のログインスクリプトを実行させます。その後環境変数 DASHINIT に HOME の下の起動毎の初期化ファイル名を設定します。 # dasinit.rc の例 set 'PS1=dash\>' set 'path=c:/windows;c:/bin;c:/usr/bin;c:/etc' set "DASHINIT=. ~/dash.rc" # # dashlogin.rc が存在する場合それを実行する # if [ -r ~/dashlogin.rc ]; then . ~/dashlogin.rc set "DASHINIT=. ~/dash.rc" # # .dashlogin が存在する場合 # elif [ -r ~/.dashlogin ]; then . ~/.dashlogin set "DASHINIT=. ~/.dashrc" fi 起動前に環境変数 DASHINIT にコマンドを設定しておくことで、C:/etc/Dashinit 等のカレントにない別のファイルを dashinit.rc の代わりに用いることができます。 ●シェルスクリプトの実行 「#!」で始まるファイルを、直接ファイル名でコマンド実行させるようなことは、こ のシェル自身は行いません。 また同様に .BAT を特別視しませんので、COMMAND.COM のバッチファイルを実行す る場合は、「COMMAND.COM /C ??.BAT」のようにしなければなりません。 ●サンプル関数 alias 別名定義です。name というコマンドを cmd に置換して実行します。 csh のような alias コマンドです。(ちょっと不完全かもしれない) function alias { if [ "$2" ];then shift function $0 "$@ \$@" elif [ -z "$2" ];then function fi } pushd popd pushd は現在のカレントディレクトリを保存して、dir に移動しま す。popd するたびに1つ前の場所に戻ります。5箇所まで保存しま す。 function pushd { @ "PUSHDP=(${PUSHDP-0}+1)%5" set PD$PUSHDP=$PWD cd $@ } function popd { eval "=cd \$PD$PUSHDP" @ "PUSHDP=($PUSHDP-1)%5" } read [] 標準入力から文字列を読み取り環境変数に設定します。msg を書い た場合はプロンプト文字列として最初に表示します。 function read { if [ "$1" ];then if [ "$2" ];then echo -n "$2";fi set "$1=$<" fi } yes_no [] Y か N のキーが押されるまで待ちます(入力キーは大文字小文字ど ちらでもよい)。YES または NO の文字を、変数 var に代入して返 します。msg を書いた場合はプロンプト文字列として最初に表示し ます。(例) yes_no KEY "(Y/N)?" function yes_no { if [ "$2" ];then echo -n "$2";fi lwhile eval '@ "_=$GETKEY&223"' '[ "(($_=89)|($_=78))" -eq 0' if [ "$1" ];then if [ $_ -eq 89 ];then set $1=YES else set $1=NO fi fi } ●行編集の拡張例 作者の定義している設定 (付属の dashinit.rc も参考にしてください) # CTRL+L で画面消去 ctrlkey 12 160 function c12 'echo -n \c[*' # CTRL+F で前の行の n 番目の単語呼び出し ctrlkey 13 129 function c13 'set "EL=$@"' ctrlkey 6 132 function c6 { set _=${GETKEY:s} set "_=${EL:w$_}" } # CTRL+D でシェル終了 ctrlkey 4 128 function c4 'exit' この設定をしておくと、例えば dash> cp c:/bin/dash.exe f:/bin という行を実行したあとで dash> rm [CTRL]+[F] [2] ~~~~~~~~~~~~~~~~~ とキータイプすると、前の行の2つ目の単語が取り出されて dash> rm c:/bin/dash.exe のように展開されます。こんな感じで、いろいろ工夫して使ってみて下さい。 ●欠点 おそらく、動作確認が不完全です。移植したばかりでまだ使用していない機能が存 在します。特に WindowsNT 上での動作は、作者は一切テストしていません。 エラーメッセージ出力がいいかげんです。X68000 版から移植するとき、エラーコー ドの違いを吸収するために正しいコマンド終了値を返さないことがあります。これは エラーコードやメッセージの問題だけで、エラーチェック自体は行っています。 Human68k 版時の各種制限 (行長制限255byteやバッファサイズなど) がそのまま 残っています。 行単位で読み捨て実行なので、前の行に戻る制御文が存在しません。その代わり関 数定義を使えば、ブロック全体のループ(lfor,lwhile)ができます。 その他、作者は自分で最初から知っててそのままにしている部分がいろいろありま す。例えば cd コマンドが Symbolic Link を戻れない、行内編集が弱い、ls b:/ が ls b:/* としなければ使えないなど、これらは全部仕様です。必要なら外部コマンド を alias (function) して使用してください。 ●配布、利用について このプログラムおよび付属ファイルの著作権はすべて作者が保持しています。この 条件に従う場合に限り、プログラムの自由な配布、転載が可能です。配布や転載時に、 特に連絡して許可を取る必要はありません。 ただし、ドキュメントやプログラムの無断改変、そしてドキュメント内容をこのプ ログラムと無関係なものに引用や転用して利用することは堅く禁じます。 このプログラムの動作は無保証です。このプログラムの使用に起因する症状および 損害もすべて利用者の責任とします。 ●VersionList Human68K dash.x 199?/??/?? 1.00 元はKoアプリ集のFD起動SYS用シェル&スクリプト言語として開発 1993/08/27 1.08 1994/04/16 1.11 1995/01/30 1.15 Ko-Window kodash.win 1995/02/06 1.15 X68000 Ko-Window の Window版(WindowGUI版) Human68K dash.x 1995/05/25 1.16 X68000最終版、実行ファイルでわずか15Kbyte Win32 dash.exe 1998/02/14 1.20 Win32用に移植(Win95/98) 1998/02/20 1.21 $USERNAME追加,エラー出力リダイレクトのバグ修正,パイプ機能実装 more.exe 付属 MI Zaurus mpfp 1999/06/01 1.21 ZaurusOS に移植 1999/06/02 1.21 R0602 外部プロセス起動他デバッグ 1999/06/05 1.21 R0605 スレッド制御に変更。ヒストリ、ペン入力、エスケープシー ケンス、ファイル名補完、more/dumpコマンド追加等 1999/06/06 1.21 R0606 デバイスファイル名対応,dcp,screen,keypadコマンド追加など 1999/06/09 1.21 R0609 ファイル名をOSへ渡すときドライブ名を大文字変換するように した。cp コマンドのエンバグ修正。 1999/12/23 1.21 R1223 rmコマンドでワイルドカードを使うとすべてのファイルが消 えないバグ修正。dfコマンドで残り容量以外が正しく表示されてい なかったので、各パラメータがちゃんと表示されるようにした。df コマンドにドライブ名を直接与える事ができなかったので、これに 対応した。df S1: といった裏技めいた指定もできるようになって しまった。起動時の画面クリア、カーソル表示関連、キー入力バッ ファリングその他細かい修正。 2000/12/02 1.21 R2000 スレッド管理の問題で、タイミングによってデッドロックし てしまう現象を修正した(XTALのqueueとeventを使用)。これにより、 デッドロックしやすかった MI-EX1/TR1/C1/P10 でも dash を安心 して使えるようになった。 2000/12/18 1.21 R2001 とりあえず縦画面に対応してみた。キーボードアイコンを左 上の角に位置変更した。 2001/05/05 1.21 R2505 E1/C1/P10/L10/EX1/TR1 のファイルシステムのディレクトリ に対応。F0:\ にアクセスできるのを発見。P10 の FileSearchDir() のバグ(?)対策を施した。 Win32 dash.exe 2006/08/11 1.22 環境変数の長さ制限を変更 2006/10/02 1.23 NT系でリダイレクトが利かないバグを修正 2006/10/26 1.24 lsが長いファイル名に対応していなかったバグ修正 2006/11/02 1.25 カーソルキー上下でもヒストリをたどれるよう変更 2006/11/02 1.26 行編集機能追加 2007/02/11 1.27 ~ の展開でハングアップするバグ修正 ●連絡先 小笠原博之 oga (at) art.udn.ne.jp http://www.vector.co.jp/authors/VA004474/