NAME

BATsh::CMD - Pure Perl cmd.exe interpreter for BATsh

SYNOPSIS

# Used internally by BATsh; not normally called directly.
BATsh::CMD::exec_block('BATsh::CMD', \@lines, _batsh => $batsh);

# Read ERRORLEVEL after execution
my $rc = BATsh::CMD::errorlevel('BATsh::CMD');

DESCRIPTION

BATsh::CMD implements the Windows cmd.exe command set entirely in Perl. No external cmd.exe is required.

Supported Commands

ECHO text, ECHO., ECHO OFF/ON, @ECHO OFF
SET VAR=value, SET /A expr (arithmetic with + - * / % ^ & | ~ << >>)
SET /P VAR=PromptString (interactive prompt input)
IF "A"=="B" ... ELSE ..., IF /I (case-insensitive), IF NOT
IF EXIST "path with spaces", IF DEFINED var, IF ERRORLEVEL n
FOR %%V IN (list) DO ...
FOR /L %%V IN (start,step,end) DO ...
FOR /F "options" %%V IN (source) DO ...
GOTO :label, :label, GOTO :EOF
CALL :label [args], CALL file.batsh
SETLOCAL [ENABLEDELAYEDEXPANSION|DISABLEDELAYEDEXPANSION], ENDLOCAL
CD [/D] [path], DIR, COPY [/Y], DEL, MOVE, MKDIR, RMDIR [/S /Q]
REN, TYPE, PAUSE, EXIT [/B] [code], CLS, TITLE, VER, PUSHD, POPD
SHIFT, SHIFT /N
cmd1 | cmd2  (pipeline via temporary file)
cmd1 & cmd2  (sequential)
cmd1 && cmd2  (conditional-and)
cmd1 || cmd2  (conditional-or)

I/O redirection: > file stdout overwrite >> file stdout append < file stdin 2> file stderr overwrite 2>> file stderr append 2>&1 stderr to stdout

Variable Expansion

%VAR% references are expanded before each line executes. Variable names are case-insensitive (stored in uppercase internally).

Inside parenthesised IF and FOR bodies, %VAR% is expanded at parse time (before the block runs), matching cmd.exe's behaviour. To observe a value updated inside the same block, enable delayed expansion:

SETLOCAL ENABLEDELAYEDEXPANSION
SET X=old
IF 1==1 (
    SET X=new
    ECHO !X!    &:: new  -- delayed, runtime
    ECHO %X%    &:: old  -- immediate, parse-time
)
ENDLOCAL

Escape Character

The ^ character escapes the following character:

ECHO a^&b      ->  a&b    (& not a compound separator)
ECHO a^^b      ->  a^b    (literal ^)
ECHO hello^    ->  helloworld  (^ at end-of-line joins next line)
world

I/O Redirection

CMD > file      stdout overwrite
CMD >> file     stdout append
CMD 2> file     stderr overwrite
CMD 2>> file    stderr append
CMD < file      stdin from file

^> is an escaped > and is not treated as a redirect.

Compound Commands

cmd1 & cmd2     run cmd2 unconditionally after cmd1
cmd1 && cmd2    run cmd2 only if cmd1 succeeded (ERRORLEVEL 0)
cmd1 || cmd2    run cmd2 only if cmd1 failed    (ERRORLEVEL != 0)

FOR /F Options

tokens=1,2-4   which token columns to capture (1-based)
tokens=1*       token 1 to %%a; remainder to %%b
delims=CHARS    field separator characters (default: space and tab)
skip=N          skip first N lines
eol=C           skip lines beginning with C (default: ;)
usebackq        "file" reads a file; 'cmd' runs a command

Sources: bare filename, "quoted filename", 'command', or ("literal string").

ERRORLEVEL

IF ERRORLEVEL n is true when ERRORLEVEL >= n (not equality). ECHO does not reset ERRORLEVEL (unlike some broken implementations).

Accessors

BATsh::CMD::errorlevel('BATsh::CMD')        -- current ERRORLEVEL
BATsh::CMD::set_errorlevel('BATsh::CMD', n) -- set ERRORLEVEL
BATsh::CMD::echo_on('BATsh::CMD')           -- current ECHO state

AUTHOR

INABA Hitoshi <ina@cpan.org>

LICENSE

Same as Perl itself.