2022年5月
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31        
無料ブログはココログ

« 2007年3月 | トップページ | 2007年5月 »

2007年4月30日 (月)

テキストファイルを数値順にソートするバッチファイル

バッチファイルだけで、数値順にソートします。

フィルタではありません。

数値順ソート.CMD テキストファイル >出力

@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
(FOR /F %%0 IN ('FIND.EXE /C /V ""') DO SET N=%%0) <%1
SET M=1
:L1
SET N=%N:~1%
SET /A M*=10
IF DEFINED N GOTO L1
(FOR /F "USEBACKQ DELIMS=" %%0 IN (%1) DO @(
FOR /F "TOKENS=1*" %%1 IN ("%%0") DO @(
SET /A N=M+%%1 >NUL
CALL ECHO %%N%% %%0
)
)
)|FOR /F "TOKENS=1*" %%1 IN ('SORT.EXE') DO @ECHO:%%2

2007年4月29日 (日)

テキストファイルを文字順/数値順にソートするバッチファイル

WindowsのSORTコマンドは文字順のソートしか出来ません。
そこで、JScriptのArrayオブジェクトを利用して、数値順にソートします。

フィルタです。

数値順ソート.CMD <入力 >出力

@if(0)==(0) ECHO OFF
CScript.exe //NoLogo //E:JScript "%~f0"
GOTO :EOF
@end
var Lines=new Array();
while(!WScript.StdIn.AtEndOfStream) Lines.push(WScript.StdIn.ReadLine());
Lines.sort(function(a,b){return parseInt(a,10)-parseInt(b,10);});
for(var i in Lines) WScript.StdOut.WriteLine(Lines[i]);

文字順ソート.CMD <入力 >出力

@if(0)==(0) ECHO OFF
CScript.exe //NoLogo //E:JScript "%~f0"
GOTO :EOF
@end
var Lines=new Array();
while(!WScript.StdIn.AtEndOfStream) Lines.push(WScript.StdIn.ReadLine());
for(var i in Lines.sort()) WScript.StdOut.WriteLine(Lines[i]);

2007年4月26日 (木)

システムエラーコードからメッセージテキストを取り出す。

Excelがあれば、Win32APIのFormatMessage()を呼び出して、
システムエラーコードからメッセージテキストを取り出せます。
ExcelのApplication.ExecuteExcel4Macro()メソッドを利用します。

Set Application=CreateObject("Excel.Application")
Text="&H80070000"
Do
  Code=InputBox(Code,"Enter System Error Code",Text)
  If Code="" Then Exit Do
  If IsNumeric(Code) Then
    Code2=Code
    Text=Application.ExecuteExcel4Macro("CALL(""kernel32"",""FormatMessageA"",""5JJJJCJJ"",4096,0," & CLng(Code) & ",0,""" & Space(128) & """,128,0)")
  Else
    Text=Code2
  End If
Loop

2007年4月25日 (水)

インターネットからファイルをダウンロードする。

Excelがあれば、スクリプトからWin32APIのURLDownloadToFile()を呼び出して、
インターネットからファイルをダウンロードできます。

Set Application=CreateObject("Excel.Application")
CD=CreateObject("Scripting.FileSystemObject").GetAbsolutePathName("")
Call Application.ExecuteExcel4Macro("CALL(""kernel32"",""SetCurrentDirectoryA"",""JC"","""&CD&"\..\"")")
Do
  URL=InputBox("URLを入力してください。")
  If URL="" Then Exit Do
  Path=Application.GetSaveAsFileName("*.*","すべてのファイル,*.*")
  If Path=False Then Exit Do
  RC=Application.ExecuteExcel4Macro("CALL(""urlmon"",""URLDownloadToFileA"",""JJCCJJ"",0,"""&URL&""","""&Path&""",0,0)")
  If RC Then
    MsgBox Join(Array(URL,Path,Hex(RC)),vbLf),vbCritical,"失敗"
    Err.Raise &H80070000 Or (&HFFFF& And RC)
  Else
    MsgBox Join(Array(URL,Path,RC),vbLf),vbInformation,"成功"
  End If
Loop

2007年4月24日 (火)

WindowsアプリからCScript.exeのコンソール入出力を使用する。

Win32APIのAllocConsole()のスクリプトバージョンみたいなものです。

VB6、EXCEL VBA、IE、HTA、WScriptなどのWindowsアプリから、
CScript.exeを起こして、コンソールを開き、コンソール入出力を行います。

以下は、Windowsアプリ側のサンプルです。
VBSファイルですが、VB/VBAのコードに貼り付けても使えます。

Set ie = CreateObject("InternetExplorer.Application")
Set wShell = CreateObject("WScript.Shell")
wShell.Run "CScript.exe ""CScript.VBS"" " & ie.Hwnd
For k = 1 To 10
  If Not IsEmpty(ie.GetProperty("WScript")) Then
    Set W = ie.GetProperty("WScript")
    If TypeName(W) = "IHost_Class" Then Exit For
  End If
'  WScript.Sleep 100
'  Application.Wait Now + TimeSerial(0, 0, 1)
  wShell.Run "ping localhost -n 2",0,True
Next
'wShell.Popup TypeName(W) & vbTab, 5, "GetCScript", vbInformation
W.Echo "echo"
W.StdOut.WriteLine "stdout"
W.StdErr.WriteLine "stderr"
W.StdOut.Write "Enter stdin ? "
MsgBox W.StdIn.ReadLine, vbSystemModal, "GetCScript"
If vbYes = MsgBox("WScript.Quit ?" & vbTab, vbYesNo + vbQuestion, "GetCScript") Then W.Quit
MsgBox "Exit OK ?" & vbTab & vbTab, vbQuestion, "GetCScript"
'ie.Quit

[説明]

WScriptオブジェクトを受け渡しするために、IEを利用します。
IEはウィンドウハンドルで識別します。
CScript.exe側を起動します。
WSH以外での利用を想定してWScript.Sleep()をpingで代替しています。
WScriptオブジェクトをここでは変数[W]で受け取ります。
[WScript].Echo
[WScript].StdOut
[WScript].StdErr
[WScript].StdIn
などが使用できます。
[WScript].Quit
すると、CScript.exeは終了し、コンソールがすぐ閉じます。
Windowsアプリ側が終了してIEの参照を解放するか、IEを終了すると、
それをCScript.exe側が検知して、終了します。
この場合、コンソールを閉じる前にプロンプトします。

以下は、CScript.exeのWScriptオブジェクト(IHost_Class)を提供する部品側の
サンプルです。

CScript.VBS

Set Shell=CreateObject("Shell.Application")
For Each ie In Shell.Windows()
  If ie.hwnd=CLng(WScript.Arguments.Item(0)) Then Exit For
Next
ie.PutProperty "WScript",WScript
Do While TypeName(ie)="IWebBrowser2"
  WScript.Sleep 1000
Loop
MsgBox "Ended. Close OK ?"&vbTab,vbQuestion,WScript.ScriptName
WScript.StdOut.Write "Ended. Close OK ?"
WScript.StdIn.Read(1)

[説明]

Windowアプリ側に渡すため、WScriptオブジェクトをIEに渡します。
受け渡し用のIEが存在する間、待ち合わせをします。
Windowアプリ側が終了すると、IEが終了するので、抜けます。
コンソールがすぐ閉じないよう、MsgBoxかコンソールに問い合わせます。
これはどちらか選択してください。

2007年4月23日 (月)

漢字や熟語の読みがなを調べる。

Excelがあれば、かな漢字変換の逆変換ができます。

Set Application=CreateObject("Excel.Application")
Items=Array("漢字や熟語を入力してください。")
Text="読みがなを調べます"
Do
  Text=InputBox(Join(Items,vbLf),Text)
  If Text="" Then Exit Do
  Items=GetPhonetic(Text)
Loop

Function GetPhonetic(Text)
Dim Items
Items=Array()
Phonetic=Application.GetPhonetic(Text)
Do While Phonetic<>""
  Push Items,Phonetic
  Phonetic=Application.GetPhonetic()
Loop
GetPhonetic=Items
End Function

Sub Push(Items,Item)
ReDim Preserve Items(UBound(Items)+1)
Items(UBound(Items))=Item
End Sub

2007年4月22日 (日)

コマンドラインで、サスペンド(スタンバイ)、ハイバネーション(休止)する。(その2)

Excel経由でWin32APIのSetSuspendState()を使います。

サスペンド(スタンバイ)します。

CreateObject("Excel.Application")
.ExecuteExcel4Macro "CALL(""PowrProf.dll"",""SetSuspendState"",""JJJJ"",0,0,0)"

ハイバネーション(休止)します。

CreateObject("Excel.Application")
.ExecuteExcel4Macro "CALL(""PowrProf.dll"",""SetSuspendState"",""JJJJ"",1,0,0)"

コマンドラインで、サスペンド(スタンバイ)、ハイバネーション(休止)する。

シャットダウン(電源断、リブート、ログオフ)は、コマンドがありますが、
サスペンド(スタンバイ)やハイバネーション(休止)はありません。

そこで、SendKeysで"Windows タスク マネージャ"のメニューを操作して、
サスペンド(スタンバイ)します。

Set wShell=CreateObject("WScript.Shell")
wShell.SendKeys "^+{esc}"
Do While Not wShell.AppActivate("Windows タスク マネージャ")
  WScript.Sleep 100
Loop
'wShell.SendKeys "%u"
wShell.SendKeys "%ub%fx" 'スタンバイ
'wShell.SendKeys "%uh%fx" '休止状態
'wShell.SendKeys "%uu%fx" 'コンピュータの電源を切る
'wShell.SendKeys "%ur%fx" '再始動
'wShell.SendKeys "%ul%fx" 'ログオフ

コメント箇所を以下に変えると、ハイバネーション(休止)します。

wShell.SendKeys "%uh%fx" '休止状態

2007年4月21日 (土)

WSH以外のホスト環境でのWScript.Sleep()の代替関数(その3)

Excelがあれば、Win32APIが使えます。

Set Application=CreateObject("Excel.Application")

Sub Sleep(mSec)
Call Application.ExecuteExcel4Macro("CALL(""Kernel32"",""Sleep"",""JJ"","&mSec&")")
End Sub

Sleep ミリ秒

ミリ秒を指定します。

1回目は多少(数百ミリ秒~数秒)の時間が余計に掛かりますが、
2回目以降は数十ミリ秒のオーバヘッドに落ち着きます。

WSH以外のホスト環境でのWScript.Sleep()の代替関数(その2)

WMIを使用します。

Sub Sleep(mSec)
On Error Resume Next
GetObject("winmgmts:{impersonationLevel=impersonate}").ExecNotificationQuery _
  ("select * from __instancecreationevent where targetinstance isa 'Win32_NTLogEvent'") _
  .NextEvent mSec
End Sub

Sleep ミリ秒

ミリ秒を指定します。

1回目は多少(数百ミリ秒~数秒)の時間が余計に掛かりますが、
2回目以降は50~70ミリ秒のオーバヘッドに落ち着きます。

WSH以外のホスト環境でのWScript.Sleep()の代替関数

「待ち/Sleep」は、WSH環境では、WScript.Sleep()が使えますが、
IE、HTA、WSCなどのホスト環境では、WScript.Sleep()が使えません。
その代替方法です。

ping.exeを使用します。

Sub Sleep(Sec)
CreateObject("WScript.Shell").Run "ping.exe localhost -n "&(Sec+1),0,True
End Sub

Sleep 秒

秒を指定します。

1回目は多少(数秒)の時間が余計に掛かりますが、
2回目以降は数百ミリ秒のオーバヘッドに落ち着きます。

2007年4月20日 (金)

バッチファイル自身の実行結果をファイルに残すバッチファイル

バッチファイルをCMD/Cで起動するコマンドラインを作れば、
バッチファイルの実行結果をファイルに残すことは出来ます。
しかし、バッチファイルだけで、ダブルクリックなどで、
そのまま起動して、自身の実行結果をファイルに残すことは
出来ません。
そこを、起動されたら自身の実行結果をファイルに残します。

(方式-1)

バッチファイルの先頭に以下の3行を付加します。

call :main >"%~dp0LOG.TXT" 2>&1 <nul %*
goto :eof
:main

ここでは、バッチファイルと同じフォルダの"LOG.TXT"を指定しています。
ファイル名や上書き/追加書き、標準エラーを別ファイル、は好きにしてください。

もし、バッチファイル内のコマンドで、コンソールに出力したり、
コンソールから入力するときは、
>&3
2>&3
<&3
のようにリダイレクトしてください。

コンソールから入力するときは、<nul を取り除いてもよい。

%0は、:mainになります。
バッチファイル内で%0を使用しているときは、次の方法がよいかも。
%~f0などは、バッチファイル名に展開されます。

(方式-2)

バッチファイルの先頭に以下に1行を付加します。

if not "%~0"=="%~dp0.\%~nx0" "%~dp0.\%~nx0" >"%~dp0LOG.TXT" 2>&1 <nul %*

自身のバッチファイルを再帰呼び出ししています。
ここで、リカージョンを防止するために、
バッチファイルのパス表記を細工(非正規化/冗長化)しています。
これには、"%~dp0.\%~nx0"のほか、"%~f0\..\%~nx0"も使えます。

2007年4月19日 (木)

起動されたら自身のバッチファイルを最小化で起動し直すバッチファイル

ショートカットファイルや別のバッチファイルを作れば、
バッチファイルを最小化で起動することは出来ます。
しかし、バッチファイルだけで、ダブルクリックなどで、
そのまま起動して、最小化にすることは出来ません。
そこで、起動されたら自身のバッチファイルを最小化で起動し直します。

バッチファイルの先頭に以下に1行を付加します。

@if not "%~0"=="%~dp0.\%~nx0" start /min cmd /c,"%~dp0.\%~nx0" %* & goto :eof

或いは、以下の4行

@if not "%~0"=="%~dp0.\%~nx0" (
start /min cmd /c,"%~dp0.\%~nx0" %*
goto :eof
)

自身のバッチファイルを再帰呼び出ししています。
このとき、リカージョンを防止するために、
バッチファイルのパス表記を細工(非正規化/冗長化)しています。
これには、"%~dp0.\%~nx0"のほかに、"%~f0\..\%~nx0"も使えます。

(注) もし、cmd /c,"の,がないとドロップ時などに失敗します。

2007年4月18日 (水)

WSFファイルをCMDファイルにする呪文(テキストヘッダ)

WSFファイルをCScript.exeで実行するのは、いろいろと面倒です。
それが、WSFファイルの先頭に呪文(テキストヘッダ)を付加して、
拡張子をCMDに変えることで、簡単にできます。

WSFファイルの先頭に以下の6行を追加して、拡張子をCMDに変更します。

@(
REN "%~f0" "%~nx0.wsf"
CScript.exe //NoLogo "%~f0.wsf" %*
REN "%~f0.wsf" "%~nx0"
GOTO :EOF
)

XMLの厳密な構文<?XML ?>では駄目です。寛容な構文で使えます。

実行中はファイルの拡張子が一時的に.CMD.wsfに変更されます。
なので、多重実行は出来ません。
また、CTRL-Cなどで実行を中断すると、拡張子が元に戻りません。
そのときは、手作業でファイル名を元に直してください。

2007年4月17日 (火)

ファイルやフォルダをごみ箱に送るバッチファイル(XP)

XPまでは、FolderItem.InvokeVerb('delete')は同期、Shell.NameSpace(10).MoveHere(FolderItem)は非同期です。

確認付き削除.CMD ファイルやフォルダ...

@if(0)==(0) ECHO OFF
FOR %%0 IN (%*) DO CScript.exe //NoLogo //E:JScript "%~f0" "%%~dp0" "%%~nx0"
GOTO :EOF
@end
new ActiveXObject('Shell.Application').NameSpace(WScript.Arguments.Item(0)).Items().Item(WScript.Arguments.Item(1)).InvokeVerb('delete');

確認なし削除.CMD ファイルやフォルダ...

@if(0)==(0) ECHO OFF
FOR %%0 IN (%*) DO CScript.exe //NoLogo //E:JScript "%~f0" "%%~dp0" "%%~nx0"
GOTO :EOF
@end
var Shell=new ActiveXObject('Shell.Application');
var Folder=Shell.NameSpace(WScript.Arguments.Item(0));
var FolderItem=Folder.Items().Item(WScript.Arguments.Item(1));
Shell.NameSpace(10).MoveHere(FolderItem);
while(Folder.Items().Item(WScript.Arguments.Item(1))) WScript.Sleep(100);

2007年4月14日 (土)

タスクスケジューラやショートカットから非表示で起動されるバッチファイル

タスクスケジューラやATコマンド、スタートアップ、ショートカットなどから
非表示で起動されるバッチファイルの作り方と、
それを起動するコマンドラインの書き方です。

バッチファイルの先頭と末尾にそれぞれ、以下の1行を付加します。

hoge.cmd

@if(0==0)WScript.Quit(new ActiveXObject('WScript.Shell').Run('"'+WScript.ScriptFullName+'"',0,true));@else
REM ここからバッチファイル
notepad.exe 起動の確認です。
REM ここまでバッチファイル
:@end

このバッチファイルを

WScript.exe //E:JScript hoge.cmd

で起動します。

2007年4月13日 (金)

空のZIPファイルを新規作成するバッチファイル

NewZIP.CMD [ZIPファイル名]

@if(0)==(0) ECHO OFF
CScript.exe //NoLogo //E:JScript "%~f0" %*
GOTO :EOF
@end
var Usage="Usage: NewZIP.CMD [ZIPfile]";
if(WScript.Arguments.Count()>1){
  WScript.Echo(Usage);
  WScript.Quit();
}
var fso=new ActiveXObject("Scripting.FileSystemObject");
if(WScript.Arguments.Count()==1){
  var ZIPfile=WScript.Arguments.Item(0);
}else{
  var ZIPfile="新規圧縮 (zip 形式) フォルダ.zip";
}
if(fso.GetExtensionName(ZIPfile).toUpperCase()!="ZIP"){
  WScript.Echo("Invalid Extension Name -",ZIPfile);
  WScript.Quit();
}
if(fso.FileExists(ZIPfile)){
  WScript.Echo("Already exsists. -",ZIPfile);
}else{
  var File=fso.CreateTextFile(ZIPfile,false);
  File.Write("PK" + String.fromCharCode(5,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0));
  File.Close();
}
WScript.Quit();

2007年4月12日 (木)

ZIPファイルの中身を一覧するバッチファイル

ListZIP.CMD ZIPファイル...

@if(0)==(0) ECHO OFF
CScript.exe //NoLogo //E:JScript "%~f0" %*
GOTO :EOF
@end
var Usage="Usage: ListZIP.CMD ZIPfiles...";
if(WScript.Arguments.Count()==0){
  WScript.Echo(Usage);
  WScript.Quit();
}
for(var e=new Enumerator(WScript.Arguments);!e.atEnd();e.moveNext()){ 
  ListZip(e.item());
}
WScript.Quit();

function ListZip(ZIPfile){
var COL=8;
var fso=new ActiveXObject("Scripting.FileSystemObject");
if(fso.GetExtensionName(ZIPfile).toUpperCase()!="ZIP"){
  WScript.Echo("Invalid Extension Name -",ZIPfile);
  WScript.Quit();
}
var Shell=new ActiveXObject("Shell.Application");
var Folder=Shell.NameSpace(fso.GetAbsolutePathName(ZIPfile));
var Rows=new Array();
Rows.push(ZIPfile);
var Columns=new Array();
for(var k=0;k<=COL;k++){
  Columns.push(Folder.GetDetailsOf(null,k));
}
Rows.push(Columns.join('\t'));
for(var e=new Enumerator(Folder.Items());!e.atEnd();e.moveNext()){
  var FolderItem=e.item();
  var Columns=new Array();
  for(var k=0;k<=COL;k++){
    if(k==5){
      Columns.push(FolderItem.Size);
    }else{
      Columns.push(Folder.GetDetailsOf(FolderItem,k));
    }
  }
  Rows.push(Columns.join('\t'));
}
WScript.Echo(Rows.join('\n'));
}

2007年4月10日 (火)

ZIPファイルの中身を削除するバッチファイル

DeleteZIP.CMD ZIPファイル ファイルまたはフォルダ名...

@if(0)==(0) ECHO OFF
CScript.exe //NoLogo //E:JScript "%~f0" %*
GOTO :EOF
@end
var Usage="Usage: DeleteZIP.CMD ZIPfile files...";
if(WScript.Arguments.Count()<2){
  WScript.Echo(Usage);
  WScript.Quit();
}
var ZIPfile=WScript.Arguments.Item(0);
var fso=new ActiveXObject("Scripting.FileSystemObject");
if(fso.GetExtensionName(ZIPfile).toUpperCase()!="ZIP"){
  WScript.Echo("Invalid Extension Name -",ZIPfile);
  WScript.Quit();
}
var Shell=new ActiveXObject("Shell.Application");
var Folder=Shell.NameSpace(fso.GetAbsolutePathName(ZIPfile));
for(var k=1;k<WScript.Arguments.Count();k++){
  var FileName=WScript.Arguments.Item(k);
  var FolderItem=Folder.ParseName(FileName);
  if(!FolderItem){
    WScript.Echo(FileName,"- Not Found.");
    break;
  }
//  FolderItem.InvokeVerb("delete");
  FolderItem.InvokeVerb("削除(&D)");
}
WScript.Quit();

2007年4月 7日 (土)

ZIPファイルを作成/追加/置換するバッチファイル

MakeZIP.CMD ZIPファイル名 ファイル...

@if(0)==(0) ECHO OFF
CScript.exe //NoLogo //E:JScript "%~f0" %*
GOTO :EOF
@end
var Usage="Usage: MakeZIP.CMD ZIPfile files...";
if(WScript.Arguments.Count()<2){
  WScript.Echo(Usage);
  WScript.Quit();
}
var ZIPfile=WScript.Arguments.Item(0);
var fso=new ActiveXObject("Scripting.FileSystemObject");
if(fso.GetExtensionName(ZIPfile).toUpperCase()!="ZIP"){
  WScript.Echo("Invalid Extension Name -",ZIPfile);
  WScript.Quit();
}
if(!fso.FileExists(ZIPfile)){
  var File=fso.CreateTextFile(ZIPfile,false);
  File.Write("PK" + String.fromCharCode(5,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0));
  File.Close();
}
var wShell=new ActiveXObject("WScript.Shell");
var vbYesNoCancel=3;
var vbQuestion=32;
var vbYes=6;
var vbNo=7;
var vbCancel=2;
var Shell=new ActiveXObject("Shell.Application");
var zFolder=Shell.NameSpace(fso.GetAbsolutePathName(ZIPfile));
F1:for(var k=1;k<WScript.Arguments.Count();k++){
  var Path=WScript.Arguments.Item(k);
  var FileName=fso.GetFileName(Path);
  var sFolderItem=Shell.NameSpace(fso.GetParentFolderName(fso.GetAbsolutePathName(Path))).ParseName(FileName);
  if(!sFolderItem){
    WScript.Echo(Path,"- Not Found.");
    break;
  }
  W1:while(true){
    var zFolderItem=zFolder.ParseName(FileName);
    if(!zFolderItem){
      var Count=zFolder.Items().Count;
      zFolder.CopyHere(sFolderItem);
      while(zFolder.Items().Count<=Count) WScript.Sleep(100);
      break;
    }else{
      var Ans=wShell.PopUp("このフォルダには既に次のファイルが存在します:\n\n"+
                 '"' + FileName + '"\n\n既存のファイルと置き換えますか?',
                 0,"ファイル置換の確認",vbYesNoCancel+vbQuestion);
      switch(Ans){
      case vbYes:
        zFolderItem.InvokeVerb("delete");
        break;
      case vbNo:
        break W1;
      case vbCancel:
        break F1;
      }
    }
  }
}
WScript.Quit();

2007年4月 6日 (金)

FORコマンドからの途中脱出

(1) バッチファイル内のFORコマンドからの途中脱出は、
GOTO ラベル

複文内にラベルは置けません。
なのでGOTO文は必然的に途中脱出になります。
ただし、途中脱出後もDO部が空ECHOされます。変なの。

for /l %%k in (1,1,10) do (
if %%k==5 goto :next
echo %%k
)
:next

(2) パイプ前後のFORコマンドからの途中脱出は、
EXIT

パイプ前後のコマンドは、CMD/Cの子CMDプロセスで実行されるので、
GOTO文は書けませんが、逆にEXITは書けます。

more|for /l %%k in (1,1,10) do (
(if %%k==5 exit)
echo %%k
)

(3) バッチファイル外のFORコマンドからの途中脱出は、
CMD /S /Cで実行して、EXIT

バッチファイル外では、ラベルやGOTO文は無効です。

cmd /s /c "for /l %k in (1,1,10) do ((if %k==5 exit)& echo %k)"

2007年4月 5日 (木)

SET /Pはパイプをうまく読めない。(障害)

例えば、HOGE.CMDが

@ECHO OFF
SETLOCAL
SET /P X=
ECHO X=%X%
SET /P Y=
ECHO Y=%Y%
SET /P Z=
ECHO Z=%Z%

のとき、

HOGE.CMD <HOGE.CMD

はちゃんと読めます。しかし、

MORE HOGE.CMD|HOGE.CMD

の結果は無茶苦茶です。同じ入力なのに結果はばらばらです。
1行の途中で分割したり、空読みしたり、読み飛ばしたり。

回避方法はありません。SET /Pを使わないことです。

2007年4月 4日 (水)

パイプ前後の複文中のECHOの行末に空白が付く。

(
echo aaa
echo bbb
)|hoge

では、

"aaa "
"bbb "

のようにECHOの行末に空白が付きます。

パイプの前後は、子CMDプロセスで実行されますが、
このとき、複文がcmd.exeによって、
cmd.exe /S /D /c" ( echo aaa & echo bbb )"
のように1行に整形されます。
こうして空白が付加されます。

したがって回避方法は、自分で複文を1行に整形する。

cmd /s /c "echo aaa&echo bbb"|hoge

或いは、複文を別のバッチファイルにする。

sub.cmd|hoge

« 2007年3月 | トップページ | 2007年5月 »