« 2009年1月 | トップページ | 2009年3月 »

2009年2月23日 (月)

ファイル名に%を使うと、バッチファイルにドロップしたとき、環境変数に展開される。

もし、ファイル名に%cd%や%temp%などの環境変数似の文字列があると、バッチファイルにドロップしたときに、環境変数に展開されちゃいます。
これは、"~"では、エスケープできません。

これを回避するには、バッチ変数(%1など)を使わないことです。
じゃ、どうやってファイル名を受け取るのかって?
バッチ変数の代わりにCMDCMDLINEを参照します。

SET ARG=%CMDCMDLINE:*" =%
SET ARG=%ARG:~0,-1%
ECHO;%ARG%
PAUSE

あるいは、CMDCMDLINEからバッチ変数に代入し直します。

SETLOCAL ENABLEDELAYEDEXPANSION
SET ARG=!CMDCMDLINE:*" =!
SET ARG=!ARG:~0,-1!
CALL :MAIN !ARG:%%=%%%%!
GOTO :EOF
:MAIN
REM 元のバッチファイルをここに置く
ECHO;%*
PAUSE

2009年2月19日 (木)

ファイル名に&を使うときは、半角空白も併せて使うべし。(その2)

複数ファイルのドロップにも対応するには、CMDCMDLINEをパーズします。

@echo off
setlocal enabledelayedexpansion
set cmdline=!cmdcmdline:*" =!
set cmdline=!cmdcmdline:~0,-1!
set fq=
set fg=
set fb=true
set cmdline2=
set n=0
if not defined cmdline goto :next
:for
  set c=!cmdline:~%n%,1!
  if not defined c goto :next
  if defined fq (
    if !c!==^" set fq=& if defined fg set cmdline2=!cmdline2!^"
  ) else (
    if !c!==^  if not defined fb (
      set fb=true
      if defined fg (
        set fg=
        set cmdline2=!cmdline2!^"
      )
    )
    if not !c!==^  if defined fb (
      set fb=
      if not !c!==^" (
        set fg=true
        set cmdline2=!cmdline2!^"
      )
    )
    if !c!==^" set fq=true& if defined fg set cmdline2=!cmdline2!^"
  )
  set cmdline2=!cmdline2!!c!
  set /a n+=1
  goto :for
:next
if defined fq set cmdline2=!cmdline2!^"& if defined fg set cmdline2=!cmdline2!^"
if defined fg set cmdline2=!cmdline2!^"
call :main !cmdline2!
exit
:main
rem 元のバッチファイルをここに置く
echo;%*
pause

2009年2月18日 (水)

ファイル名に&を使うときは、半角空白も併せて使うべし。

もし、ファイル名に&を使っていて、パス名に半角空白がないと、バッチファイルにドロップしたときに、&以降がコマンドとして実行されちゃいます。桑原桑原
もし、パス名に半角空白があれば、"~"でエスケープされるので、安全です。

バッチ側でこの問題を回避するには、CMDCMDLINEを使います。

1ファイルだけなら、手抜きですが、以下を試してみてください。

SETLOCAL ENABLEDELAYEDEXPANSION
SET ARG=!CMDCMDLINE:*" =!
SET ARG="!ARG:"=!"
ECHO;!ARG!
PAUSE
EXIT

2009年2月11日 (水)

ファイル名に=;,や全角空白を含むファイルをバッチファイルにドロップすると、ファイル名が分割される。(その4)

バッチファイル側、バッチファイル機能だけで対処します。

@echo off
setlocal enabledelayedexpansion
set cmdline=%*
set fq=
set fg=
set fb=true
set cmdline2=
set n=0
if not defined cmdline goto :next
:for
  set c=!cmdline:~%n%,1!
  if not defined c goto :next
  if defined fq (
    if !c!==^" set fq=& if defined fg set cmdline2=!cmdline2!^"
  ) else (
    if !c!==^  if not defined fb (
      set fb=true
      if defined fg (
        set fg=
        set cmdline2=!cmdline2!^"
      )
    )
    if not !c!==^  if defined fb (
      set fb=
      if not !c!==^" (
        set fg=true
        set cmdline2=!cmdline2!^"
      )
    )
    if !c!==^" set fq=true& if defined fg set cmdline2=!cmdline2!^"
  )
  set cmdline2=!cmdline2!!c!
  set /a n+=1
  goto :for
:next
if defined fq set cmdline2=!cmdline2!^"& if defined fg set cmdline2=!cmdline2!^"
if defined fg set cmdline2=!cmdline2!^"
call :main !cmdline2!
goto :eof
:main
rem 元のバッチファイルをここに置く
echo;%*

2009年2月 5日 (木)

IF ERRORLEVELの零判定

ERRORLEVELが負数のときには、
IF ERRORLEVEL 1 ECHO 正
IF NOT ERRORLEVEL 1 ECHO 零または負
なので、零判定、非零判定に使えまへん。

ほな、どないしまひょ。零判定は2段重ねかな。

IF ERRORLEVEL 0 IF NOT ERRORLEVEL 1 ECHO 零
IF NOT ERRORLEVEL 1 IF ERRORLEVEL 0 ECHO 零

一方、非零判定は、正と負の二つに分かれてしまいます。

IF ERRORLEVEL 1 (ECHO 正) ELSE IF ERRORLEVEL 0 (ECHO 零) ELSE ECHO 負

ERRORLEVELを絶対値に変換すれば楽かも。

IF NOT ERRORLEVEL 0 CMD/CEXIT %ERRORLEVEL:~1%
IF ERRORLEVEL 1 ECHO 非零
IF NOT ERRORLEVEL 1 ECHO 零

IF ERRORLEVELを使わない零判定なんてのもあります。

CMD/CEXIT %ERRORLEVEL% && ECHO 零 || ECHO 負

« 2009年1月 | トップページ | 2009年3月 »