BATsh
view release on metacpan or search on metacpan
echo out > /tmp/out.txt
BATSH
# Perl 5.005_03 and later; pure-Perl, no external shell required.
DESCRIPTION
Executive Summary
BATsh is a bilingual shell interpreter written in pure Perl. It runs
cmd.exe batch syntax and bash/sh syntax in the same script file,
switching automatically between CMD mode and SH mode on a line-by-line
basis. No external cmd.exe, bash, or sh is required -- everything runs
inside Perl.
Mixed-Mode Sample
The following script demonstrates cmd.exe and bash sections coexisting
and sharing variables through the common BATsh::Env variable store.
:: -- CMD section: sets a variable and calls a SH function via bridge --
@ECHO OFF
SET LANG=BATsh
SET COUNT=3
# -- SH section: reads CMD variables, uses functions and pipeline --
greet() {
echo "Hello from $1 (bash/sh mode)"
}
greet $LANG
for i in 1 2 3; do echo " item $i of $COUNT"; done
result=$(echo "$LANG" | perl -ne "print uc")
echo "Uppercase: $result"
echo "log line" >> /tmp/batsh_demo.txt
:: -- CMD section again: reads variable set by SH side --
ECHO Back in CMD mode
ECHO Uppercase result: %result%
BATsh features (both modes): pipelines (|), I/O redirection (> >> <
2>&1), variable expansion (${var%pat} ${var^^} ${#var}), functions,
shift, local.
FULL DESCRIPTION
BATsh is a bilingual shell interpreter written in pure Perl. It
implements both the cmd.exe command set and the sh/bash command set
entirely in Perl -- no external cmd.exe, bash, or sh is required.
Scripts are divided into CMD sections (uppercase first token) and SH
sections (lowercase first token). Both sections share a common variable
store via BATsh::Env, so variables set in a CMD section are immediately
visible in the next SH section and vice versa.
CMD MODE
Any line whose first token is all uppercase (A-Z, 0-9, path chars) is a
CMD line. CMD sections are executed by BATsh::CMD, which implements:
ECHO, @ECHO OFF/ON
SET VAR=value, SET /A expr (arithmetic)
SET /P VAR=Prompt (interactive prompt input from STDIN)
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 (s,step,e) DO ...
FOR /F "tokens= delims= skip= eol= usebackq" %%V IN (src) DO ...
GOTO :label, :label, GOTO :EOF
CALL :label [args], CALL file.batsh
SHIFT, SHIFT /N
SETLOCAL [ENABLEDELAYEDEXPANSION|DISABLEDELAYEDEXPANSION], ENDLOCAL
CD, DIR, COPY, DEL, MOVE, MKDIR, RMDIR, REN, TYPE
PAUSE, EXIT [/B] [code], CLS, TITLE, VER, PUSHD, POPD
cmd1 | cmd2 (pipeline via temporary file)
&, &&, || (sequential, conditional-and, conditional-or)
Variable Expansion
"%VAR%" references are expanded before each line is dispatched. Variable
names are case-insensitive ("SET foo=x" is visible as "%FOO%").
Inside parenthesised IF and FOR blocks, "%VAR%" is expanded at parse
time (before any commands in the block run), matching cmd.exe behaviour.
To see a value updated inside a block, use delayed expansion:
SETLOCAL ENABLEDELAYEDEXPANSION
SET X=old
IF 1==1 (
SET X=new
ECHO !X! &:: prints "new" (delayed)
ECHO %X% &:: prints "old" (parse-time)
)
ENDLOCAL
Batch Parameters
%0 is the script path (absolute); %1..%9 are positional arguments; "%*"
is all arguments joined by space.
"CALL :label arg1 arg2 ..." invokes a subroutine as a true call frame:
the subroutine receives its own %0 (the ":label" token), %1..%9 (the
call arguments) and "%*" (their join), and the caller's parameters are
saved before the call and restored on return. Arguments are "%"-expanded
before the call and split with double-quote awareness, so "CALL :sub "a
b" %FILE%" passes "a b" as one argument and the expanded value of
"%FILE%" as the next. Nested calls each get an independent frame. The
same arguments are also visible as $1..$9 / $@ when the subroutine body
is written in SH mode.
"SHIFT" moves %2 into %1, %3 into %2, and so on, clears %9, and rebuilds
"%*"; "SHIFT /N" begins the shift at %N (%1.."%(N-1)" are left
unchanged).
Batch-parameter tilde modifiers expand %0..%9 components:
%~0 dequote (strip surrounding "...")
%~f1 full absolute path of %1
%~d1 drive letter only (e.g. C:)
%~p1 directory path only (with trailing /)
%~n1 filename without extension
%~x1 extension only (e.g. .bat)
%~dp0 drive + directory (most common usage)
%~nx1 filename + extension
Redirection and Compound Commands
ECHO text > file stdout overwrite
ECHO text >> file stdout append
prog 2> err.txt stderr redirect
& cmd sequential execution
( run in 0.734 second using v1.01-cache-2.11-cpan-3c2a17b8caa )