Windows/Batch Programming
Shell Scripts on the PC
This began as a project to write a set of essays for use by my co-workers as an aid to understanding the DOS batch programs I wrote for user account and machine management, and for numerous one-off programs to solve problems and provide unusual services. It got out of hand. Win95, with its brain-dead batch language, came along - then NT and its very different batch language - then DOS started going away and Linux appeared on the scene.
It appeared to me that the best way to continue the work was to make the original essays into one volume of a multi-volume work covering all of the environments I use in separate sets of essays. This is the master wrapper page and introduction for that grand scheme. I don't expect it ever to be complete - the operating environments come and go faster than I can master their shell script languages. If the links are not active, I haven't actually written anything on that topic yet.
echo
Turn off echo command:
@echo off
print blank line:
echo.
print text and variables:
echo Hello %name%, how are you?
sleep
Implementing the WAIT Command in a Batch File - DOS and Batch Files:
wait.bat:
@ping 127.0.0.1 -n 2 -w 1000 > nul @ping 127.0.0.1 -n %1% -w 1000> nul
beep
@echo off :repeat rem - character created with [ctrl]+[g] echo � ping 127.0.0.1 -n 1 -w 1000 > nul goto repeat
Current Folder
%~dp0
showfolder.bat:
%systemroot%/explorer.exe %~dp0
error levels
WARNING: Error levels match equal OR HIGHER
some_program.exe IF ERRORLEVEL 1 GOTO ERROR GOTO DONE :ERROR echo "There was an error" exit 1 :DONE echo "done"
print exit code from last run command: (case insensitive)
echo %errorlevel% echo %ERRORLEVEL%
using errorlevel within batch:
if errorlevel 1 ( rem this includes all 1 and above ... )
To determine the exact return code the previous command returned, we could use a construction like this:
@ECHO OFF IF ERRORLEVEL 1 SET ERRORLEV=1 IF ERRORLEVEL 2 SET ERRORLEV=2 IF ERRORLEVEL 3 SET ERRORLEV=3 IF ERRORLEVEL 4 SET ERRORLEV=4 • • • IF ERRORLEVEL 254 SET ERRORLEV=254 IF ERRORLEVEL 255 SET ERRORLEV=255 ECHO ERRORLEVEL = %ERRORLEV%
Negative Error Levels:
- In Windows NT 4/2000/XP this may sometimes fail, since some executables return negative numbers for errorlevels!
- However, this can be fixed by using the following code to check for non-zero return codes:
- IF %ERRORLEVEL% NEQ 0 ...
- Use the code above wherever you would have used IF ERRORLEVEL 1 ... in the "past".
Source: Batch files - Errorlevels
Return Code
On modern windows, it looks like you can get the exit code with:
echo %ErrorLevel% 0 - success 1+ - error
exit
Quits the CMD.EXE program (command interpreter) or the current batch
script.
EXIT [/B] [exitCode]
/B specifies to exit the current batch script instead of
CMD.EXE. If executed from outside a batch script, it
will quit CMD.EXE
exitCode specifies a numeric number. if /B is specified, sets
ERRORLEVEL that number. If quitting CMD.EXE, sets the proces
exit code with that number.
To exit with return code of 1:
exit 1
To exit from one batch file to another with return code of 1:
exit /b 1
if
Performs conditional processing in batch programs.
IF [NOT] ERRORLEVEL number command IF [NOT] string1==string2 command IF [NOT] EXIST filename command
- NOT Specifies that Windows 2000 / XP should carry out the command only if the condition is false.
- ERRORLEVEL number Specifies a true condition if the last program run returned an exit code equal to or greater than the number specified.
- string1==string2 Specifies a true condition if the specified text strings match.
- EXIST filename Specifies a true condition if the specified filename exists.
- command Specifies the command to carry out if the condition is met. Command can be followed by ELSE command that will execute the command after the ELSE keyword if the specified condition is FALSE
The ELSE clause must occur on the same line as the command after the IF. For example:
IF EXIST filename. ( del filename. ) ELSE ( echo filename. missing. )
if %1==yes echo yes if "%1"=="" echo empty if not %1==no echo no if %1=="doit" ( echo doing it ) if %1=="domore" ( echo doing more echo doing more ) if "%1"=="" ( echo Error: missing parameter exit 1 )
Note: Careful, spaces in variables will break if statements
Resources:
comments
REM
rem this is a comment rem and so is this
End of line comment: [1]
cd .. &REM this is an end of line comment
variables
rem notice no space between equal sign set variablename=johnson set variablename=mike johnson echo My name is %variablename%
set rc=%errorlevel%
Command line parameters (notice no second %)
%1 %2 %3 %4 %5 %6 %7 %8 %9 shift
String Manipulation
Substring Extraction
Substring Extraction: Extract portions of a string using the syntax %variable:~start_index,length%. start_index defines the starting position (0-based), and length specifies the number of characters to extract. Negative start_index values count from the end of the string.
Syntax
%variable:~start_index%
%variable:~start_index,length%
This can include negative numbers:
%variable:~start_index, -length%
%variable:~-start_index,length%
%variable:~-start_index,-length%
ref: How-to: Extract part of a variable (substring) - https://ss64.com/nt/syntax-substring.html
String Concatenation
String Concatenation: Combine strings using the %var1%%var2% syntax.
set combined=%str1% %str2%!
String Replacement
String Replacement: Replace substrings within a string using %variable:old_string=new_string%.
echo %string:test=example%
String Length
String Length: Determine the length of a string by using for loop and variable substitution to remove characters until the string is empty.
set string=HelloWorld
set count=0
:loop
if not "%string%"=="" (
set string=%string:~1%
set /a count+=1
goto loop
)
String Tokenization
String Tokenization: Split a string into tokens based on delimiters using a for loop.
set string=apple,banana,orange
for /f "tokens=1-3 delims=," %%a in ("%string%") do (
echo Token 1: %%a
echo Token 2: %%b
echo Token 3: %%c
)
Removing Spaces
Removing Spaces: Remove spaces using string substitution.
set string=%string: =%
Trimming Spaces
Trimming Spaces: Trim leading and trailing spaces using a for loop and variable substitution.
set string=" leading and trailing spaces "
for %%a in ("%string%") do set trimmed=%%~a
echo "%trimmed%"
for loop
for %%a in (1 2 3 4 5 6 7 8 9 10 11 12 13 14 15) do echo CHEESE && echo IS GOOD
# same affect if you don't care about value for %%a in (1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1) do echo CHEESE && echo IS GOOD
for /f %%x in ('dir %BACKUPDIR% /b ^| find /v /c "::"') do set countfiles=%%x
for %%a in (1 2 3 4 5 6 7 8 9 10 11 12 13 14 15) do ( ... echo "loop: %%a" )
References:
goto loop
set a=1
set limit=1111111111111111111111111 :loop ... set a=%a%1 if not %a%==%limit% goto loop
References:
function
set ARG1=test1 call:FUNC1 set ARG1=test2 call:FUNC1 :FUNC1 echo. echo "ARG1 = %ARG1%" echo. goto:eof
Resources:
pause
pause pause > nul
wait or sleep
Window XP does not have a wait command. Here is a work around:
wait.bat:
@ping 127.0.0.1 -n 2 -w 1000 > nul @ping 127.0.0.1 -n %1% -w 1000> nul
to use:
wait.bat 10 # 10 seconds
To make the "ping" timing more accurate, just be shure to ping something that does not exist.
@ping 1.1.1.1 -n 1 -w 10000
Source: http://malektips.com/dos0017.html
Since Windows XP and 2003 users do not have the CHOICE command, if you find the PING alternative not to your liking, the Windows 2003 Resource Kit has a batch file SLEEP command.
Multiple commands in one
The double ampersand (&&) command separator may not run the commands to the right of && command.
For example, when you run the following command, the pause command does not run when a floppy disk is not in drive A, and you receive a "The device is not ready" message:
dir a: && pause
Source: http://support.microsoft.com/kb/279253
exec copy *.* c:\Dir + cls + del a:\*.txt
Source: http://www.computing.net/answers/dos/cascading-multiple-dos-commands/15543.html
Call Batch
C:\>call /?
Calls one batch program from another.
CALL [drive:][path]filename [batch-parameters]
batch-parameters Specifies any command-line information required by the
batch program.
If Command Extensions are enabled CALL changes as follows:
CALL command now accepts labels as the target of the CALL. The syntax
is:
CALL :label arguments
A new batch file context is created with the specified arguments and
control is passed to the statement after the label specified. You must
"exit" twice by reaching the end of the batch script file twice. The
first time you read the end, control will return to just after the CALL
statement. The second time will exit the batch script. Type GOTO /?
for a description of the GOTO :EOF extension that will allow you to
"return" from a batch script.
In addition, expansion of batch script argument references (%0, %1,
etc.) have been changed as follows:
%* in a batch script refers to all the arguments (e.g. %1 %2 %3
%4 %5 ...)
Substitution of batch parameters (%n) has been enhanced. You can
now use the following optional syntax:
%~1 - expands %1 removing any surrounding quotes (")
%~f1 - expands %1 to a fully qualified path name
%~d1 - expands %1 to a drive letter only
%~p1 - expands %1 to a path only
%~n1 - expands %1 to a file name only
%~x1 - expands %1 to a file extension only
%~s1 - expanded path contains short names only
%~a1 - expands %1 to file attributes
%~t1 - expands %1 to date/time of file
%~z1 - expands %1 to size of file
%~$PATH:1 - searches the directories listed in the PATH
environment variable and expands %1 to the fully
qualified name of the first one found. If the
environment variable name is not defined or the
file is not found by the search, then this
modifier expands to the empty string
The modifiers can be combined to get compound results:
%~dp1 - expands %1 to a drive letter and path only
%~nx1 - expands %1 to a file name and extension only
%~dp$PATH:1 - searches the directories listed in the PATH
environment variable for %1 and expands to the
drive letter and path of the first one found.
%~ftza1 - expands %1 to a DIR like output line
In the above examples %1 and PATH can be replaced by other
valid values. The %~ syntax is terminated by a valid argument
number. The %~ modifiers may not be used with %*
Check if Programming Running
tasklist /FI "IMAGENAME eq myapp.exe" 2>NUL | find /I /N "myapp.exe">NUL if "%ERRORLEVEL%"=="0" echo Programm is running
Ref: http://stackoverflow.com/questions/162291/how-to-check-if-a-process-is-running-via-a-batch-script
Kill Program
taskkill /IM cmd.exe
# force taskkill /F /IM process.exe
Ref: http://superuser.com/questions/57941/exit-program-in-windows-command-prompt
Start Window
C:\>start /?
Starts a separate window to run a specified program or command.
START ["title"] [/Dpath] [/I] [/MIN] [/MAX] [/SEPARATE | /SHARED]
[/LOW | /NORMAL | /HIGH | /REALTIME | /ABOVENORMAL | /BELOWNORMAL]
[/WAIT] [/B] [command/program]
[parameters]
"title" Title to display in window title bar.
path Starting directory
B Start application without creating a new window. The
application has ^C handling ignored. Unless the application
enables ^C processing, ^Break is the only way to interrupt
the application
I The new environment will be the original environment passed
to the cmd.exe and not the current environment.
MIN Start window minimized
MAX Start window maximized
SEPARATE Start 16-bit Windows program in separate memory space
SHARED Start 16-bit Windows program in shared memory space
LOW Start application in the IDLE priority class
NORMAL Start application in the NORMAL priority class
HIGH Start application in the HIGH priority class
REALTIME Start application in the REALTIME priority class
ABOVENORMAL Start application in the ABOVENORMAL priority class
BELOWNORMAL Start application in the BELOWNORMAL priority class
WAIT Start application and wait for it to terminate
command/program
If it is an internal cmd command or a batch file then
the command processor is run with the /K switch to cmd.exe.
This means that the window will remain after the command
has been run.
If it is not an internal cmd command or batch file then
it is a program and will run as either a windowed application
or a console application.
parameters These are the parameters passed to the command/program
If Command Extensions are enabled, external command invocation
through the command line or the START command changes as follows:
non-executable files may be invoked through their file association just
by typing the name of the file as a command. (e.g. WORD.DOC would
launch the application associated with the .DOC file extension).
See the ASSOC and FTYPE commands for how to create these
associations from within a command script.
When executing an application that is a 32-bit GUI application, CMD.EXE
does not wait for the application to terminate before returning to
the command prompt. This new behavior does NOT occur if executing
within a command script.
When executing a command line whose first token is the string "CMD "
without an extension or path qualifier, then "CMD" is replaced with
the value of the COMSPEC variable. This prevents picking up CMD.EXE
from the current directory.
When executing a command line whose first token does NOT contain an
extension, then CMD.EXE uses the value of the PATHEXT
environment variable to determine which extensions to look for
and in what order. The default value for the PATHEXT variable
is:
.COM;.EXE;.BAT;.CMD
Notice the syntax is the same as the PATH variable, with
semicolons separating the different elements.
When searching for an executable, if there is no match on any extension,
then looks to see if the name matches a directory name. If it does, the
START command launches the Explorer on that path. If done from the
command line, it is the equivalent to doing a CD /D to that path.
Wait for window program to complete
A windows program normally returns immediately upon startup. To wait until the process completes.
start /wait [program]
Advanced Windows Commands
wmic
windows management
List Disk and Network Drives
Loop volume verify: [1]
@echo off rem listdrives.bat by Kenneth Burgener <kenneth@oeey.com> © Nov 2012 echo Available Drives: for %%a in (A B C D E F G H I J K L M N O P Q R S T U V W X Y Z) do ( rem echo %%a:: vol %%a: 1>NUL 2>NUL && echo %%a: )
Windows Vista and Windows 7: [2]
wmic logicaldisk get name
List physical drives like \\.\PHYSICALDRIVE1 [3]
wmic diskdrive list wmic diskdrive list brief
Examples
Perl PPM Module Installer
@echo off set PPM_MODULE=Spreadsheet-BasicRead call:PPM set PPM_MODULE=Spreadsheet-WriteExcel call:PPM set PPM_MODULE=Frontier-RPC call:PPM set PPM_MODULE=File-Copy-Recursive call:PPM set PPM_MODULE=Error call:PPM set PPM_MODULE=Statistics-Basic call:PPM goto END :PPM echo. echo Installing %PPM_MODULE%... call c:\perl\bin\ppm.bat install %PPM_MODULE% if errorlevel 1 ( echo. echo !!! echo !!! ERROR: Failure to install %PPM_MODULE% echo !!! goto END ) echo. goto:eof :END
run10jobs.bat
REM c:\RSD_TEST_TOOLS\seqtp18_32.exe -B k:\test1 64K 1000M 0 k_log set window_title="E:\test1 64K 1000M:" set command_line=C:\RSD\seqtp18_32.exe -S E:\test1 64K 1000M 0 E_log start %window_title% %command_line% %SystemRoot%\system32\taskkill /IM seqtp18_32.exe /F