BATsh

 view release on metacpan or  search on metacpan

lib/BATsh.pm  view on Meta::CPAN

  %~dp0  drive + directory    (most common usage)
  %~nx1  filename + extension

=head2 Redirection and Compound Commands

  ECHO text > file      stdout overwrite
  ECHO text >> file     stdout append
  prog 2> err.txt       stderr redirect
  & cmd                 sequential execution
  cmd1 && cmd2          run cmd2 only if cmd1 succeeded (ERRORLEVEL 0)
  cmd1 || cmd2          run cmd2 only if cmd1 failed   (ERRORLEVEL != 0)

The C<^> character escapes the next character:

  ECHO a^&b    prints  a&b   (& not treated as compound separator)
  ECHO a^^b    prints  a^b
  ECHO text^   next line is joined (line continuation)

=head1 SH MODE

Any line whose first token contains a lowercase letter is a SH line.
SH sections are executed by BATsh::SH, which implements:

  VAR=value, export VAR=value, unset VAR
  echo, printf
  if/then/elif/else/fi
  for VAR in list; do ... done
  while condition; do ... done
  until condition; do ... done
  case $var in pat1|pat2) ... ;; *) ... ;; esac
    (|-patterns, * ? [abc] [a-z] [!abc] globs, ;& and ;;& fall-through)
  test / [ ... ]  (file, string, and integer comparisons)
  cd, pwd, exit, true, false, :, read, shift [N], local VAR=value
  trap 'cmd' SIG... / trap - SIG / trap '' SIG / trap [-p]  (EXIT + %SIG)
  $(( arithmetic )) -- +, -, *, /, %, and $1..$9 inside
  $( command ) and `command`  (command substitution, nested)
  cmd1 | cmd2 [| cmd3 ...]  (pipeline via temporary file)
  cmd1 && cmd2, cmd1 || cmd2, cmd1 ; cmd2  (compound commands)
  > >> < 2> 2>> 2>&1 1>&2  (I/O redirection)
  name() { ... }, function name { ... }  (function definitions)
  $VAR, ${VAR}, $1..$9, $@, $*, $#, $?, $$, $0
  ${VAR:-default}, ${VAR:=default}, ${VAR:+alt}
  ${VAR%pat}, ${VAR%%pat}   -- shortest/longest suffix removal
  ${VAR#pat}, ${VAR##pat}   -- shortest/longest prefix removal
  ${VAR/pat/rep}, ${VAR//pat/rep}  -- first/all substitution
  ${VAR^^}, ${VAR^}, ${VAR,,}, ${VAR,}  -- case conversion
  ${VAR:N:L}, ${VAR:N}  -- substring
  ${#VAR}  -- string length
  arr=(a b c), arr+=(d e), arr[i]=v, arr[i]+=v  -- indexed arrays
  declare -a arr, declare -A map, typeset ...   -- array declaration
  map=([k]=v ...), map[k]=v                     -- associative arrays
  ${arr[i]}, ${map[key]}, $arr (== ${arr[0]})   -- element access
  ${arr[@]}, ${arr[*]}, ${#arr[@]}, ${#arr[i]}, ${!arr[@]}
  unset arr, unset arr[i]
  source / . file

=head1 REQUIREMENTS

Perl 5.005_03 or later. Core modules only. No external shell required.

=head1 BUGS AND LIMITATIONS

Commands that are not built in -- C<FINDSTR>, C<SORT>, C<MORE>, C<CHOICE>,
C<TIMEOUT>, C<XCOPY>, C<ROBOCOPY> and the like in CMD mode, and any
non-builtin program in SH mode -- are B<not> reimplemented in Perl. They
are invoked as external programs (via Perl's C<system>), so they work only
where the host operating system provides the corresponding executable
(e.g. F<FINDSTR.EXE> on Windows). This is by design: only the built-in
command set is guaranteed to run identically on every platform.

The built-in CMD interpreter does not implement:

=over

=item * C<FOR /F> with C<usebackq> backtick-quoted commands on Windows
(the C<cmd /c> subprocess path is untested on Windows).

=back

Variable substring C<%VAR:~n,m%> / C<%VAR:~n%> / C<%VAR:~-n%> / C<%VAR:~n,-m%>
and in-place substitution C<%VAR:str1=str2%> / C<%VAR:*str1=str2%> are B<now
supported> as of version 0.05 (see L<BATsh::Env>).

Dynamic pseudo-variables C<%DATE%> (YYYY-MM-DD), C<%TIME%> (HH:MM:SS.cc),
C<%CD%> (current directory), C<%RANDOM%> (0-32767), C<%ERRORLEVEL%>, and
C<%CMDCMDLINE%> are B<now supported> as of version 0.05.

Indexed and associative arrays -- C<arr=(a b c)>, C<arr+=(...)>,
C<arr[i]=v>, C<declare -A map>, C<map=([k]=v ...)>, C<${arr[i]}>,
C<${arr[@]}>, C<${#arr[@]}>, C<${!arr[@]}>, and C<unset arr[i]> -- are
B<now supported> as of version 0.06 (see L<BATsh::SH>).  Element ordering
for C<${arr[@]}> is ascending numeric index for indexed arrays and sorted
key order for associative arrays (bash leaves the latter unspecified);
C<"${arr[@]}"> word-splits to one item per element in C<for> lists.

The built-in SH interpreter does not implement:

=over

=item * Tilde expansion C<~/path> and C<~user> (only C<cd> with no
argument uses C<$HOME>).

=item * Brace expansion C<{a,b}> and C<{1..5}>.

=item * Here-strings (C<E<lt>E<lt>E<lt> word>) and process substitution
(C<E<lt>(cmd)>, C<E<gt>(cmd)>).

=item * The shell options C<set -e>, C<set -u>, C<set -x>, and the
builtins C<getopts>, C<select>, C<alias>, C<eval> and C<exec>.

=back

C<trap> B<is> supported in SH mode: C<trap 'cmd' SIGSPEC...> registers a
handler, C<trap - SIGSPEC> resets to default, C<trap '' SIGSPEC> ignores,
and C<trap> / C<trap -p> lists.  Real signals are bridged to Perl's C<%SIG>;
the C<EXIT> pseudo-signal (also C<0>) runs when the script ends or on
C<exit>.  The handler is expanded when it fires.  See L<BATsh::SH/"Traps and
Signals">.

Common to both modes: a parenthesised group C<( ... )> does not run in a
separate sub-shell; it shares the one variable store, so there is no



( run in 0.846 second using v1.01-cache-2.11-cpan-0b5f733616e )