- /* steve jansen */
- // another day in paradise hacking code and more
- Windows Batch Scripting: Getting Started
- Getting Started with Windows Batch Scripting
- Launching the Command Prompt
- Editing Batch Files
- Viewing Batch Files
- Batch File Names and File Extensions
- Saving Batch Files in Windows
- Running your Batch File
- Comments
- Silencing Display of Commands in Batch Files
- Debugging Your Scripts
- Comments
- Guides
- Recent Posts
- Social Stuff
- /* steve jansen */
- // another day in paradise hacking code and more
- Windows Batch Scripting: Variables
- Variable Declaration
- Variable Assignment
- Reading the Value of a Variable
- Listing Existing Variables
- Variable Scope (Global vs Local)
- Special Variables
- Command Line Arguments to Your Script
- Tricks with Command Line Arguments
- Some Final Polish
- Comments
- Guides
- Recent Posts
- Social Stuff
/* steve jansen */
// another day in paradise hacking code and more
Windows Batch Scripting: Getting Started
Getting Started with Windows Batch Scripting
Windows batch scripting is incredibly accessible – it works on just about any modern Windows machine. You can create and modify batch scripts on just about any modern Windows machine. The tools come out of the box: the Windows command prompt and a text editor like Notepad.exe. It’s definitely far from the best shell scripting langauge, but, it gets the job done. It’s my “duct tape” for Windows.
Launching the Command Prompt
Windows gurus launch the command prompt using the keyboard shortcut Windows Logo Key + R (i.e., “Run”) > Type cmd.exe then Enter . This is way faster than navigating the Windows Start Menu to find the Command Prompt.
Editing Batch Files
The universal text editor for batch files is Notepad ( Windows Logo Key + R > Type notepad then Enter ). Since batch files are just ASCII text, you can probably use just about any text editor or word processor. Very few editors do anything special for Batch files like syntax highlighting or keyword support, so notepad is good enough fine and will likely be installed on just about every Windows system you encounter.
Viewing Batch Files
I would stick with Notepad for viewing the contents of a batch file. In Windows Explorer (aka, “My Computer”), you should be able to view a batch file in Notepad by right clicking the file and seleting Edit from the context menu. If you need to view the contents within a command prompt window itself, you can use a DOS command like TYPE myscript.cmd or MORE myscript.cmd or EDIT myscript.cmd
Batch File Names and File Extensions
Assuming you are using Windows XP or newer, I recommend saving your batch files with the file extension .cmd . Some seriously outdated Windows versions used .bat , though I recommend sticking with the more modern .cmd to avoid some rare side effects with .bat files.
With the .cmd file extension, you can use just about filename you like. I recommend avoiding spaces in filenames, as spaces only create headaches in shell scripting. Pascal casing your filenames is an easy way to avoid spaces (e.g., HelloWorld.cmd instead of Hello World.cmd ). You can also use punctuation characters like . or — or _ (e.g. Hello.World.cmd , Hello-World.cmd , Hello_World.cmd ).
Another thing with names to consider is avoiding names that use the same name of any built-in commands, system binaries, or popular programs. For example, I would avoid naming a script ping.cmd since there is a widely used system binary named ping.exe . Things might get very confusing if you try to run ping and inadvertently call ping.cmd when you really wanted ping.cmd . (Stay tuned for how this could happen.) I might called the script RemoteHeartbeat.cmd or something similar to add some context to the script’s name and also avoid any naming collisions with any other executable files. Of course, there could be a very unique circumstance in which you want to modify the default behavior of ping in which this naming suggestion would not apply.
Saving Batch Files in Windows
Notepad by default tries to save all files as plain jane text files. To get Notepad to save a file with a .cmd extension, you will need to change the “Save as type” to “All Files (.)”. See the screenshot below for an example of saving a script named “HelloWorld.cmd” in Notepad.
SIDEBAR: I’ve used a shortcut in this screenshot that you will learn more about later. I’ve saved the file to my “user profile folder” by naming the file %USERPROFILE%\HelloWorld.cmd . The %USERPROFILE% keyword is the Windows environmental variable for the full path to your user profile folder. On newer Windows systems, your user profile folder will typically be C:\Users\ . This shortcut saves a little bit of time because a new command prompt will generally default the “working directory” to your user profile folder. This lets you run HelloWorld.cmd in a new command prompt without changing directories beforehand or needing to specify the path to the script.
Running your Batch File
The easy way to run your batch file in Windows is to just double click the batch file in Windows Explorer (aka “My Computer”). Unfortunately, the command prompt will not give you much of a chance to see the output and any errors. The command prompt window for the script will disappear as soon as the script exits. (We will learn how to handle this problem in Part 10 – Advanced Tricks ).
When editing a new script, you will likely need to run the batch file in an existing command window. For newbies, I think the easiest foolproof way to run your script is to drag and drop the script into a command prompt window. The command prompt will enter the full path to your script on the command line, and will quote any paths containing spaces.
Some other tips to running batch files:
- You can recall previous commands using the up arrow and down arrow keys to navigate the command line history.
- I usually run the script as %COMPSPEC% /C /D «C:\Users\User\SomeScriptPath.cmd» Arg1 Arg2 Arg3 This runs your script in a new command prompt child process. The /C option instructs the child process to quit when your script quits. The /D disables any auto-run scripts (this is optional, but, I use auto-run scripts). The reason I do this is to keep the command prompt window from automatically closing should my script, or a called script, call the EXIT command. The EXIT command automatically closes the command prompt window unless the EXIT is called from a child command prompt process. This is annoying because you lose any messages printed by your script.
Comments
The official way to add a comment to a batch file is with the REM (Remark) keyword:
The power user method is to use :: , which is a hack to uses the the label operator : twice, which is almost always ignored.
Most power authors find the :: to be less distracting than REM . Be warned though there are a few places where :: will cause errors.
For example, a FOR loop will error out with :: style comments. Simply fall back to using REM if you think you have a situation like this.
Silencing Display of Commands in Batch Files
The first non-comment line of a batch file is usually a command to turn off printing (ECHO’ing) of each batch file line.
The @ is a special operator to suppress printing of the command line. Once we set ECHO’ing to off, we won’t need the @ operator again in our script commands.
You restore printing of commands in your script with:
Upon exit of your script, the command prompt will automatically restore ECHO to it’s previous state.
Debugging Your Scripts
Batch files invole a lot of trial and error coding. Sadly, I don’t know of any true debugger for Windows batch scripts. Worse yet, I don’t know of a way to put the command processor into a verbose state to help troubleshoot the script (this is the common technique for Unix/Linux scripts.) Printing custom ad-hoc debugging messages is about your only option using the ECHO command. Advanced script writers can do some trickery to selectively print debugging messages, though, I prefer to remove the debugging/instrumentation code once my script is functioning as desired.
Posted by Steve Jansen Mar 1 st , 2013 batch, scripting, shell, windows
Comments
Hi, I’m Steve. I’m a software developer loving life in Charlotte, NC, an (ISC) 2 CSSLP and an avid fan of Crossfit.
And, no, I’m not Steve Jansen the British jazz drummer, though that does sound like a sweet career.
Guides
Recent Posts
Social Stuff
- @steve-jansen on GitHub
- @steve-jansen on StackOverflow
- @steve-jansen ProTips on Coderwall
- @steve-jansen on Microsft Connect
- @steve-jansen on ASP.NET User Voice
- Subscribe via RSS
Copyright © 2015 — Steve Jansen — Powered by Octopress
/* steve jansen */
// another day in paradise hacking code and more
Windows Batch Scripting: Variables
Today we’ll cover variables, which are going to be necessary in any non-trivial batch programs. The syntax for variables can be a bit odd, so it will help to be able to understand a variable and how it’s being used.
Variable Declaration
DOS does not require declaration of variables. The value of undeclared/uninitialized variables is an empty string, or «» . Most people like this, as it reduces the amount of code to write. Personally, I’d like the option to require a variable is declared before it’s used, as this catches silly bugs like typos in variable names.
Variable Assignment
The SET command assigns a value to a variable.
NOTE: Do not use whitespace between the name and value; SET foo = bar will not work but SET foo=bar will work.
The /A switch supports arthimetic operations during assigments. This is a useful tool if you need to validated that user input is a numerical value.
A common convention is to use lowercase names for your script’s variables. System-wide variables, known as environmental variables, use uppercase names. These environmental describe where to find certain things in your system, such as %TEMP% which is path for temporary files. DOS is case insensitive, so this convention isn’t enforced but it’s a good idea to make your script’s easier to read and troubleshoot.
WARNING: SET will always overwrite (clobber) any existing variables. It’s a good idea to verify you aren’t overwriting a system-wide variable when writing a script. A quick ECHO %foo% will confirm that the variable foo isn’t an existing variable. For example, it might be tempting to name a variable “temp”, but, that would change the meaning of the widely used “%TEMP%” environmental varible. DOS includes some “dynamic” environmental variables that behave more like commands. These dynamic varibles include %DATE% , %RANDOM% , and %CD% . It would be a bad idea to overwrite these dynamic variables.
Reading the Value of a Variable
In most situations you can read the value of a variable by prefixing and postfixing the variable name with the % operator. The example below prints the current value of the variable foo to the console output.
There are some special situations in which variables do not use this % syntax. We’ll discuss these special cases later in this series.
Listing Existing Variables
The SET command with no arguments will list all variables for the current command prompt session. Most of these varaiables will be system-wide environmental variables, like %PATH% or %TEMP% .
NOTE: Calling SET will list all regular (static) variables for the current session. This listing excludes the dynamic environmental variables like %DATE% or %CD% . You can list these dynamic variables by viewing the end of the help text for SET, invoked by calling SET /?
Variable Scope (Global vs Local)
By default, variables are global to your entire command prompt session. Call the SETLOCAL command to make variables local to the scope of your script. After calling SETLOCAL , any variable assignments revert upon calling ENDLOCAL , calling EXIT , or when execution reaches the end of file (EOF) in your script.
This example demonstrates changing an existing variable named foo within a script named HelloWorld.cmd . The shell restores the original value of %foo% when HelloWorld.cmd exits.
A real life example might be a script that modifies the system-wide %PATH% environmental variable, which is the list of directories to search for a command when executing a command.
Special Variables
There are a few special situations where variables work a bit differently. The arguments passed on the command line to your script are also variables, but, don’t use the %var% syntax. Rather, you read each argument using a single % with a digit 0-9, representing the ordinal position of the argument. You’ll see this same style used later with a hack to create functions/subroutines in batch scripts.
There is also a variable syntax using ! , like !var! . This is a special type of situation called delayed expansion. You’ll learn more about delayed expansion in when we discuss conditionals (if/then) and looping.
Command Line Arguments to Your Script
You can read the command line arguments passed to your script using a special syntax. The syntax is a single % character followed by the ordinal position of the argument from 0 – 9 . The zero ordinal argument is the name of the batch file itself. So the variable %0 in our script HelloWorld.cmd will be “HelloWorld.cmd”.
The command line argument variables are * %0 : the name of the script/program as called on the command line; always a non-empty value * %1 : the first command line argument; empty if no arguments were provided * %2 : the second command line argument; empty if a second argument wasn’t provided * …: * %9 : the ninth command line argument
NOTE: DOS does support more than 9 command line arguments, however, you cannot directly read the 10th argument of higher. This is because the special variable syntax doesn’t recognize %10 or higher. In fact, the shell reads %10 as postfix the %0 command line argument with the string “0”. Use the SHIFT command to pop the first argument from the list of arguments, which “shifts” all arguments one place to the left. For example, the the second argument shifts from position %2 to %1 , which then exposes the 10th argument as %9 . You will learn how to process a large number of arguments in a loop later in this series.
Tricks with Command Line Arguments
Command Line Arguments also support some really useful optional syntax to run quasi-macros on command line arguments that are file paths. These macros are called variable substitution support and can resolve the path, timestamp, or size of file that is a command line argument. The documentation for this super useful feature is a bit hard to find – run ‘FOR /?’ and page to the end of the output.
I removes quotes from the first command line argument, which is super useful when working with arguments to file paths. You will need to quote any file paths, but, quoting a file path twice will cause a file not found error.
fI is the full path to the folder of the first command line argument
fsI is the same as above but the extra s option yields the DOS 8.3 short name path to the first command line argument (e.g., C:\PROGRA
1 is usually the 8.3 short name variant of C:\Program Files ). This can be helpful when using third party scripts or programs that don’t handle spaces in file paths.
dpI is the full path to the parent folder of the first command line argument. I use this trick in nearly every batch file I write to determine where the script file itself lives. The syntax SET parent=%
dp0 will put the path of the folder for the script file in the variable %parent% .
nxI is just the file name and file extension of the first command line argument. I also use this trick frequently to determine the name of the script at runtime. If I need to print messages to the user, I like to prefix the message with the script’s name, like ECHO %
n0: some message instead of ECHO some message . The prefixing helps the end user by knowing the output is from the script and not another program being called by the script. It may sound silly until you spend hours trying to track down an obtuse error message generated by a script. This is a nice piece of polish I picked up from the Unix/Linux world.
Some Final Polish
I always include these commands at the top of my batch scripts:
The SETLOCAL command ensures that I don’t clobber any existing variables after my script exits. The ENABLEEXTENSIONS argument turns on a very helpful feature called command processor extensions. Trust me, you want command processor extensions. I also store the name of the script (without the file extension) in a variable named %me% ; I use this variable as the prefix to any printed messages (e.g. ECHO %me%: some message ). I also store the parent path to the script in a variable named %parent% . I use this variable to make fully qualified filepaths to any other files in the same directory as our script.
Posted by Steve Jansen Mar 1 st , 2013 batch, scripting, shell, windows
Comments
Hi, I’m Steve. I’m a software developer loving life in Charlotte, NC, an (ISC) 2 CSSLP and an avid fan of Crossfit.
And, no, I’m not Steve Jansen the British jazz drummer, though that does sound like a sweet career.
Guides
Recent Posts
Social Stuff
- @steve-jansen on GitHub
- @steve-jansen on StackOverflow
- @steve-jansen ProTips on Coderwall
- @steve-jansen on Microsft Connect
- @steve-jansen on ASP.NET User Voice
- Subscribe via RSS
Copyright © 2015 — Steve Jansen — Powered by Octopress