FORコマンド中でパイプ&リダイレクトを使用する

DOSのFORコマンドは、数あるDOSのコマンド中でも 肝となる重要なコマンドです。

そのFORコマンド内で実行するコマンドに パイプやリダイレクトを使用したい場合があります。

例えば・・・

C:\>FOR /F %i IN ('DIR /B /A:-D | FIND /C /V ""') DO ECHO %i
| の使い方が誤っています。

上の例では、カレントディレクトリのファイルの数を出力しようとしているのですが 「| の使い方が誤っています。」とエラーが表示されてしまいます。

これは、FORコマンド内のパイプやリダイレクトは "^"(キャレット)を使ってエスケープしてやる必要があるためです。

正しくは、下のようになります。

C:\>FOR /F %i IN ('DIR /B /A:-D ^| FIND /C /V ""') DO ECHO %i
3

リダイレクトも同様です。

FOR /F "tokens=1,2 delims==" %i IN ('ASSOC') DO (
  IF NOT "%j" == "" (
    FOR /F "tokens=2 delims==" %k IN ('FTYPE %j 2^>nul') DO (
      ECHO %i
      ECHO  -^> %k
      ECHO.
    )
  )
)

上の例は、ファイルの関連付けを出力しているのですが、 3行目の標準エラーを捨てる「2^>nul」の「>」も エスケープしています。

MS-DOSのバッチファイルに、WSH(JScript)のコードを記述する

WSHには、標準入力からスクリプトを受け取ることができないので DOSの処理と、WSHの処理が必要な場合は、2つのファイルが必要になります。

今回は、ちょっと変わった手で1つのファイルで実行します。

@if (1==1) /*
@ECHO OFF
rem ========================================================
rem = MS-DOS 処理
rem ========================================================
:DOS
ECHO I'm MS-DOS!

:JSCRIPT
CScript //Nologo //E:JScript "%~f0" %*

GOTO :EOF
rem */
@end

/** ========================================================
  *  JavaScript 処理
  * ========================================================
 **/
// 主処理の呼び出し
WScript.quit(main(WScript.arguments.length
                , WScript.arguments));

// 主処理
function main( argc, argv ) {
    WScript.echo("I'm JScript!");
}

これを test.bat として実行すると、以下のような結果になります。

C:\>test.bat
I'm MS-DOS!
I'm JScript!

DOSの処理中に同じファイルをJScriptとして処理させています。

ポイントは先頭の「@if」から「@end」までです。 「@if」は、条件付きコンパイラというものなのですが、 この先頭が「@」なので、DOSの「@」と共存できているのです。

1行目の「/*」で、JScriptは「*/」までコメントになります。 逆にDOSの方は「GOTO :EOF」で処理終了になるので、 前半がDOS、後半がJScriptの処理を記載できます。

WSH(JScript)の起動時にDOSで受けた引数もすべて渡していますので それを元に処理することも可能です。

以下は、簡単なサンプルです。

@if (1==1) /*
@ECHO OFF
rem ========================================================
rem = MS-DOS 処理
rem ========================================================

rem 書式設定
SET SCRIPT=CScript //Nologo //E:JScript "%~f0"

rem 処理日取得
FOR /F %%i IN ('%SCRIPT% "%%m/%%d"') DO SET TODAY=%%i

rem 処理日出力
ECHO 今日は%TODAY%です。

GOTO :EOF
rem */
@end

/** ========================================================
  *  JavaScript 処理
  * ========================================================
 **/
// 主処理の呼び出し
WScript.quit(main(WScript.arguments.length
                , WScript.arguments));

// 書式付日付取得処理
function getDate( fmt ) {
    function _zero( val, len ) {
        for ( var i = 0; i < len; i++ ) {
            val = "0" + val;
        }
        return val.substr( val.length - len, len );
    }
    if ( ! fmt ) fmt = "%Y/%m/%d %H:%M:%S";
    var now = new Date();
    fmt = fmt.replace( "%Y", now.getFullYear() );
    fmt = fmt.replace( "%m", _zero(now.getMonth() + 1, 2) );
    fmt = fmt.replace( "%d", _zero(now.getDate() + 1, 2) );
    fmt = fmt.replace( "%H", _zero(now.getHours() + 1, 2) );
    fmt = fmt.replace( "%M", _zero(now.getMinutes() + 1, 2) );
    fmt = fmt.replace( "%S", _zero(now.getSeconds() + 1, 2) );
    return fmt;
}

// 主処理
function main( argc, argv ) {
    if ( argc > 0 ) {
        WScript.echo( getDate( argv(0) ) );
    } else {
        WScript.echo( getDate() );
    }
}

実行結果は以下のようになります。

C:\>test.bat
今日は02/27です。

DOSでは難しい書式付の日付をJScriptで作成してみました。

MS-DOSでテキストの内容を行番号付きで表示する

DOSには、Linuxの「cat -n」のように テキストデータに 行番号を付けて表示するコマンドがありません。

今回は、FIND コマンドを使って実現してみます。

FIND コマンドは、ファイルや標準入力の内容から キーワードが含まれる行を返してくれるコマンドです。 正規表現が使えない grep コマンドみたいなものです。

たとえば、下のようなテキストファイル test.txt があります。

あいうえお
カキクケコ
さしすせそたちつてと
 なにぬのの
  はひふへほ
や
ゆ
よ
らりるれろ
わおん

TYPE コマンドで開いて、FIND コマンドにパイプします。

C:\>TYPE test.txt | FIND /N /V "/////"
[1]あいうえお
[2]カキクケコ
[3]さしすせそたちつてと
[4] なにぬのの
[5]  はひふへほ
[6]や
[7]ゆ
[8]よ
[9]らりるれろ
[10]わおん

各行に行番号が付いて出力されました。

FIND コマンドの /N は、行番号を付けるオプション。 /V は、条件に“一致しない”場合に結果を返すオプションです。

つまり、テキストデータの中に絶対に存在しない文字列を条件にして 「それ以外の行」=「全ての行」を取得しているわけです。

MS-DOSでコマンドの実行結果を変数に入れる

UNIX/Linuxでは、コマンドの実行結果は簡単に変数に入れることができますが DOSでは、ちょっと工夫が必要です。

といっても、慣れれば呪文みたいなものなのです。 呪文のカギは FOR コマンドです。 下のサンプルでは、「TIME /T」の結果を ローカル変数 NOWTIME に入れています。

C:\>FOR /F "usebackq" %t IN (`TIME /T`) DO SET NOWTIME=%t
C:\>ECHO NOWTIME=%NOWTIME%
NOWTIME=21:57

/F は、IN の結果やリストを1行ずつ処理するオプションです。 1行ごとに DO 以下のコマンドを繰り返すわけですが、 コマンドの実行結果が1行なので、1回だけ値がセットされます。

"usebackq" は、 コマンド文の囲みに、"`"(バッククォーテーション)を 使用するオプションです。 このオプションを付けない場合、下のように シングルクォーテーションで、 コマンドを囲みます。

C:\>FOR /F %t IN ('TIME /T') DO SET NOWTIME=%t

UNIX/Linux のように「コマンドの実行はバッククォーテーションだよね」って 人は、このオプションを付けてください。

バッチファイルに書くときは、下のように書きます。

@ECHO OFF
FOR /F "usebackq" %%t IN (`HOSTNAME`) DO SET HNAME=%%t
ECHO %HNAME%

FOR コマンド内の "%" は "%%" にしなくてはなりません。

HOSTNAME は、 ホスト名を出力するコマンドです。 WindowsXP以上で、インターネットプロトコル(TCP/IP)が インストールされていると使用できます。 (ホスト名が欲しいだけならば、環境変数 %COMPUTERNAME% もあります)

Googleさんを招待する

新しくサイトを作っても どこからもリンクが貼られていなければ Google の収集ロボットも来てくれません。

新しいサイトが Google のインデックスに追加されているかどうかは、 ここで調べることができます。

もし、サイトがインデックスに追加されていなければ ここで追加してみてください。 数日もすると、Googleの収集ロボットが訪ねてくれると思います。

サイトの引越しと、Apacheのリダイレクト

サーバを借りることにしたので サイトの引越しをしました。

Googleにも引越しを伝える必要があるのですが 301のコードでリダイレクトすれば勝手に認識してくれるそうです。

リダイレクトは、こんな感じで書けます。

RewriteEngine on
RewriteRule (.*) http://www.odin.hyork.net/$1 [R=301,L]

元のサーバのApacheには、mod_rewriteを 入れていなかったので、下の方法で対応しました。

Redirect 301 / http://www.odin.hyork.net/

拡張子を省略しても実行できるワケ

DOSプロンプトでは、 exeの実行ファイルや、 batのバッチファイルは、 拡張子を省略しても実行することができます。

省略して実行できる拡張子は 環境変数 PATHEXT で、定義されています。 コマンドプロンプトで、以下のように打って調べます。

C:\>SET PATHEXT
PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH

SET は、 環境変数を設定・参照するコマンドです。 引数に環境変数名を付けると、その値を表示することができます。 引き数を付けないと、全ての環境変数と値を表示します。

以下のように拡張子だけ違うファイルがある場合、 ファイル名だけで実行すると、 環境変数 PATHEXT で 定義されている順番で実行します。

C:\>DIR /A:A /B
test.bat
test.vbs
test.wsh

C:\>test
I'm test.bat!  ← test.bat が実行された

この場合、test.com(無い)→ test.exe(無い)→ test.bat(有る)の順番で探します。 もし、test.bat を削除すると、次の検索順の test.vbs が実行されるわけです。

新しく省略したい拡張子がある場合は、この環境変数 PATHEXT に 追加すると、拡張子なしで実行できるようになります。

ちなみに検索するパス(場所)は、環境変数 PATH に 定義されている順番です。 つまり、PATH で定義されている検索するパスの順番に、 PATHEXT で定義されている拡張子の順番で探していくわけです。

簡単にフォルダのツリー図を作成する

今日紹介するのは、DOSコマンドを使って 簡単にフォルダのツリー図を作成する小ネタです。 (テレビショッピングのノリで)

まずは、以下の内容で「ctree.bat」を作成します。 別にバッチファイルを作成する必要は無いのですが せっかくなのでいつでも使えるようにファイルに しておきます。

余談ですが、バッチファイル名を コマンドと同じ(tree.bat)のようにしてしまうと コマンド実行時にバッチファイルの方が 呼ばれてしまうので コマンドとは別の名前を付けましょう。

@ECHO OFF
ECHO ^<pre^>
TREE
ECHO ^</pre^>

ECHO の後ろに出てくる "^"(キャレット)は、 DOS用のエスケープ文字です。

">" や "<" は リダイレクト用の特殊文字なので、 出力する場合は、エスケープしなければなりません。

TREE は フォルダの階層を視覚的に表示してくれるコマンドです。

C:\>TREE         ← 現在のフォルダ以下を出力
C:\>TREE \       ← 現在のドライブ以下を出力
C:\>TREE c:\test ← 指定のフォルダ以下を出力
C:\>TREE /F      ← ファイルも出力

先ほどの「ctree.bat」を実行します。

D:\Photo Files>ctree.bat > tree.html

作成された「tree.html」をWebブラウザで開くと 下のようにフォルダの階層が表示されます。

フォルダ パスの一覧:  ボリューム ローカル ディスク
ボリューム シリアル番号は 00000000 0000:0000 です
D:.
├─会社
├─家族旅行
│  ├─2005年_鳥羽
│  ├─2006年_鳥羽
│  ├─2007年_沖縄
│  └─2008年_北九州
└─プライベート
    ├─友人
    └─??

ただ、これだとフォルダのパスが表示されないので 「ctree.bat」をちょっと改造します。

@ECHO OFF
ECHO %CD%
ECHO.
ECHO ^<pre^>
TREE
ECHO ^</pre^>

%CD% は 現在のフォルダのパスが格納されている変数です。

D:\Photo Files

フォルダ パスの一覧:  ボリューム ローカル ディスク
ボリューム シリアル番号は 00000000 0000:0000 です
D:.
├─会社
├─家族旅行
│  ├─2005年_鳥羽
│  ├─2006年_鳥羽
│  ├─2007年_沖縄
│  └─2008年_北九州
└─プライベート
    ├─友人
    └─??

1行目に、フォルダのパスが表示されるようになりました。

MS-DOSで空行を出力する

意外と知られていない空行の出力です。

通常、メッセージの出力には ECHO コマンドを使用しますが、 このコマンドを引数なしで実行しても空行は出力されません。

C:\> ECHO
ECHO は <ON> です。

C:\> ECHO _ ←全角スペース
ECHO は <ON> です。

C:\> ECHO " "
" "

実は空行を表示するには、 ECHO. と、ピリオドを付けてやります。

C:\> ECHO.

ちなみピリオドを ECHO と離して書くと 普通にピリオドが出力されてしまいますので 注意してください。

C:\> ECHO .
.

tabindexを使ってみる

HTMLタグの属性に tabindex というものがあります。

TABキーでの移動順を指定するもので、 昔はIEだけだったのですが、最近ではFireFoxなどでも バッチリ対応されています。

これまた未対応のブラウザでも実害のないタグですので Webで業務システムを作る場合などは 使用を検討してみてください。

使い方は簡単です。

下のようなHTML書くだけで、フォーカスが、 text1→text3→text2の順番で移動します。

<input type="text" name="text1" tabindex="1">
<input type="text" name="text2" tabindex="3">
<input type="text" name="text3" tabindex="2">

下のサンプルのtext1にフォーカスをセットして Tabキーを押してみてください。 貴方のブラウザが対応していれば、text3にフォーカスが移動します。

横に並べると、あまり意味がありませんが 2列に配置したときなど役に立つときがあります。

ちなみに、tabindexに-1をセットすると 対応しているブラウザの場合、Tabキーではフォーカスがそこに移動しなくなります。

他にも、このtabindexは、 <p>タグなどでも使用することができます。 その場合、普段フォーカスがセットされない 文字にもフォーカスがセットされるので、 いつもと違う動きが面白いです。

Loppiで、Amazonの受け取り

ちょっと前からAmazonの配達がコンビニ(ローソン)で 受け取ることができるようになりました。

Amazonは1500円から配達が無料なので、とても便利なのですが 独り暮らしで家にあまりいないので、いつも不在通知が入ったり メール便の物は、ドアノブにぶら下げられたり 郵便受けにねじ込まれたりしていました。

今のところ対応しているコンビニは、ローソンだけのようなので 会社の近くのローソンに配達してもらいました。

セブンアンドワイなんかの場合は、レジで携帯電話のメールや 印刷してきた発注書を見せると清算できるのですが、 Amazonの場合は、Loppi端末を使うことになります。

支払は通常通りネットで済ませておくことができます。 この場合、ローソンでは受け取りだけになります。

詳しい説明は、ここを 見ると載っていますが、 ポイントは、「お問い合せ番号」と「認証番号」をメモしたものを持っていくことです。 メールで送られてきますが、メールを紛失・削除してしまった場合、 『認証番号は注文番号の下7桁、お問い合わせ番号は商品のお問い合わせ伝票番号』ですので、 アカウントサービスから確認することができます。

ただ、とっても便利なコンビニ受け取りも、 まだ慣れていない店員さんもおられるようで Loppi端末から出力されたレシートを レジに持って行ってもオロオロされることがありますので、 時間に余裕があるときに受け取るようにしましょう。 

MS-DOSのバッチファイルでサブルーチンを使う

DOSバッチファイルは サブルーチンを作ることもできます。

 1: @ECHO OFF
 2: 
 3: CALL :HOGEHOGE 1
 4: CALL :HOGEHOGE 2
 5: CALL :HOGEHOGE 3
 6: 
 7: GOTO :EOF
 8: :HOGEHOGE
 9: ECHO %1

上のバッチファイルを実行すると下のような出力結果になります。

C:\> TEST1.BAT
1
2
3

3〜5行目のCALLで8行目のHOGEHOGEラベルにジャンプします。 CALLは、バッチファイルの最後に来ると、呼び出し元に戻りますので、 3→8→9→4→8→9→5→8→9・・・と処理が移ります。

7行目の:EOFは、最初から設定されているラベルで、ファイルの最後を示しています。 5行目の処理の後に、 8行目に処理が移らないようにしています。

9行目で %1を使用して値を取得していますが、 CALLの呼び出しには引数を指定でき %1,%2・・・と入ってきます。

サブルーチンを複数使うときは、 下のように書きます。

@ECHO OFF

CALL :HOGEHOGE1 1
CALL :HOGEHOGE2 2

GOTO :EOF
:HOGEHOGE1
ECHO %1

GOTO :EOF
:HOGEHOGE2
ECHO %1

[Win]+[L]で、Windowsをロックする

Windowsのショートカットキーに [Win]+[L]というのがあります。

WindowsXPから使えるようになったショートカットキーで、 今までは、[Ctrl]+[Alt]+[Del]を押して メニューウィンドウを表示させてから ロックをかけていたのですが これだと一瞬でロックできます。 急いでトイレに行きたい時なんかも便利です。

[Win]キー関連では、以下ののショートカットキーを良く使います。

[Win]+[D]デスクトップの表示
[Win]+[E]エクスプローラの起動
[Win]+[R]ファイル名を指定して実行

Digest認証を使ってみる

Webの認証の1つにDigest認証というものがあります。

Basic認証の上位版といった感じのもので、 ユーザIDとパスワードを平文で送るBasic認証と違い 暗号化したユーザIDとパスワードを Webサーバに送るため、盗聴や改竄に対して強くなっています。

最近では、ほとんどのWebブラウザが対応しているそうで IEでもFireFoxでも使うことができましたえ。

Digest認証は以下のコマンドでパスワードファイルを作成します。 コマンド実行後にパスワードの入力を求められます。

# htdigest -c /etc/apache2/.htdigest "digest auth" testuser

Apacheの設定は以下のようになります。

Alias /site/ /var/www/digest/
<Directory "/var/www/digest">
    AuthUserFile /etc/apache2/.htdigest
    AuthName "digest auth"
    AuthType Digest
    Require valid-user
</Directory>

ほとんどBasic認証と同じです。

Basic認証と違う点は、パスワードファイルの作成時に 認証領域(この場合は"digest auth")を設定することと この値がApacheのAuthNameと一致している必要があります。

Apacheが2.2未満の場合は、AuthUserFileではなく AuthDigestFileディレクティブを使わないとエラーになります。

ホントは、これだけでOKのはずなのですが、 IEはCGIなどで?が付くURLだと正しく認証情報を作れないそうです。 (IE7からは対応されているらしいです)

IEがずっと対応しないので、 Apache側で専用に対応策を作ってくれたそうです。 下の定義をApacheの設定ファイルに追加します。

BrowserMatch "MSIE" AuthDigestEnableQueryStringHack=On

あとはauth_digestモジュールを有効にして、再起動します。

# a2enmod auth_digest
# apache2ctl graceful

これで終わりです。

ちょっと懐かしい気分にひたる小ネタ

WindowsXPで、偶然見つけた小ネタです。

まず、 「ファイ名を指定して実行」などで 「cmd」と打って DOSプロンプトを起動します。

起動したら、 おもむろに [Alt]+[Enter]を押してください。 DOSプロンプトが全画面表示になります。

「いつもこの画面見てたなぁ…」と 懐かしい気分になりました。

ちなみに、元に戻すときも、[Alt]+[Enter]です。

Amazonアソシエイトを入れてみる

Amazonアソシエイト(アフェリエイト)を入れてみました。

今このサイトを見ているWebブラウザの幅を 1024以上にすると、 画面右側に表示されます。
(画面が小さい場合は、下の方に表示されます)

Amazonのアソシエイトを入れるには、 Amazonで申込をするのですが、 ホントに5分程度で終わります。

数日でAmazonから審査結果のメールが送られてきます。 あとはサイトにAmazonへのリンクを貼るだけです。 このリンクが色々な種類があって悩まされました。

色々と試していきたいと思います。

XMLマスター:Pro(DB)直前対策セミナー(2月20日)

XMLのセミナーの紹介です。

以下、メールからの抜粋です。

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
▼1▼  「XMLマスター:プロフェッショナル(データベース)直前対策」
    セミナー開催のご案内
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

XMLコンソーシアムが「XMLマスター:プロフェッショナル(データベース)
直前対策セミナー」を下記の要領で開催いたします。

XMLマスター直前対策セミナーはこれまで受講者の皆さまから高い評価を
いただいており、受講者の方々からは、「現実的なユースケースでの話も
含まれておりとても分かり易かった」、「解説が丁寧ですごく分かりやす
かった」、「実際の問題を解きながらポイントを教えていただけ、とても
よかった」等のコメントをいただいています。また、「おかげさまで合格
しました!」といううれしいお知らせも届いております。

ぜひこの機会をお見逃し無く、ご参加をお待ちしています。

・日時:2009年2月20日(金) 13:30〜18:00 (受付開始13:00)
・会場:大森ベルポートA館 13F (株)日立製作所 来客コーナー
・受講料:2,000円(XMLコンソーシアム会員企業は無料)

XMLコンソーシアム直前対策セミナーの詳細はこちら
http://www.xmlconsortium.org/seminar08/090220/090220-info.html

開催地は東京・・・でも行きたい。

<label>タグの半分は優しさです

Webシステムを作る時に、ちょっとした優しさで付けて欲しいのが <label>タグです。

最近は画面も大きくなってきて、 小さなラジオボタンやチェックボタンを クリックするのは、結構大変だったりしませんか。

このタグは、フォームの部品とセットにして使うのですが、 タグで囲んだ文字列を、指定した部品のラベルとして扱います。 下のサンプルのように、ラベルの文字列がクリックされた時に、 その部品へのクリックが発生します。

使い方は下のようにフォーム部品のidに関連付けます。

<input type="radio" name="radio1" id="r1">
<label for="r1">radio1</label>

多くのブラウザがサポートしてますし、 サポートされてないブラウザでは何も無いのと同じです。 デメリットも特にない(と思う)ので是非使ってみてください。

ちなみにテキストボックスの場合はフォーカスがセットされます。 onclickイベントがある場合も、ちゃんと動くようです。

WinXPで、パスワードを記録させてしまった共有を解除する

「共有サーバに別のアカウントで接続したいんだけど、 パスワードを聞かれずに同じアカウントで接続されてしまうんだけど・・・」

別のプロジェクトの人から、そんな話で呼ばれて、 最初は「net use 使ってdeleteしたら大丈夫だろう」と思いながら行ってみたのですが 共有サーバには接続されているのに「net use」コマンドでは一覧に出てきません。

調べてみてわかったのですが、下の図のように接続する時に「パスワードを記録する」に チェックを入れてしまうと、「net use」コマンドでは、表示されなくなるようです。

解除するには、コントロールパネルのユーザアカウントから、自分のユーザを選んで 下の図のように左のメニューから「ネットワークパスワードを管理する」をクリックします。

「ユーザ名およびパスワードの保存」というウィンドウに現在保存されている接続の一覧が 表示されるので、対象の接続を削除してしまえばOKです。 次に接続するときにパスワードを聞いてくれます。

この辺りがWindowsの難しいところですね。

このウィンドウは、下のようにコマンドを打っても出すことができます。

C:\> rundll32.exe keymgr.dll, KRShowKeyMgr

Google サイト内検索

Amazonアソシエイト