Notes on using the default OS/2 command processor (CMD.EXE)

Introduction

The normal command processor used for command line sessions in OS/2 is CMD.EXE. Unfortunately, some aspects of its operation do not appear to be well documented. This page is an attempt to bring together such information; any suggestions for improvements are welcomed, and should be emailed to Bob Eager.

The first part of the material presented here may look fairly familiar, but persevere; you will probably learn something new if you keep reading!

Special symbols

It is probably best to start by looking at the symbols that are treated specially by CMD.EXE. Use of these symbols in (for example) filenames is discouraged, if not always actually disallowed. A brief description of the use of each symbol is included in the table below, but more details are provided later.

Symbol Description
> Redirects output, replacing existing file
>> Redirects output, appending to end of existing file
< Redirects input
| Pipes output to input
& Separates multiple commands
&& Conditional command execution (on success)
|| Conditional command execution (on failure)
() Groups commands
" Encloses filenames containing spaces
^ Enables input of special symbols as text
% Argument substitution flag

I/O redirection

The symbols <, >, >> and | are used for redirecting the input and/or output of commands. This is linked to the concept of standard I/O streams, inherited from UNIX. These streams are as follows:

Stream no Stream name Default setting Conventional usage
0 Standard input Keyboard Default input for program
1 Standard output Display Default output for program
2 Standard error Display Default error output for program

The stream numbers are useful, as we shall see later. Also, the separation of standard output and standard error can be exploited when the output of a program is to be sent to a file, but one still wishes to see error messages on the screen.

Redirection of standard I/O streams

Redirection is a very powerful feature. It means that programs which can take input from standard input, and send output to the appropriate standard output streams, can be used with files (and even with other programs) simply by the use of the appropriate symbols on the command line.

For example, to send a listing of a directory to a file, we just redirect the standard output:

DIR > Z.TMP

If we wanted to generate a file containing listings of two directories, this could be done with the use of the >> symbol, which appends to an existing file (if the file does not exist, it works the same as >):

DIR \OS2 > Y.LST
DIR \OS2\BOOT >> Y.LST

More usefully, to generate a file containing the names of all current environment variables:

SET > ENV.TXT

In the same way, if we wanted to sort the contents of ENV.TXT, and send the output to the screen, we could redirect the standard input of the SORT command:

SORT < ENV.TXT

The next stage is to eliminate the ENV.TXT file, run the SET and SORT commands at the same time, and connect the standard output of SET to the standard input of SORT; the connection is done using something called a pipe, but all you have to do is use the pipe symbol between the commands:

SET | SORT

Lastly, to send the sorted output directly to the file SORTENV.TXT:

SET | SORT > SORTENV.TXT

You can join several commands together in this way, forming a pipeline. It is also possible to use a pipe fitting (not a standard OS/2 feature) to drain off a copy of the data at some intermediate point, perhaps for logging purposes.

The order of the < and > redirections on the command line is immaterial, but naturally the | usage is position dependent.

Filters

Commands that read from standard input and write to standard output, performing some useful processing on the way, are often known as filters. Such programs are particularly valuable when used as part of a pipeline. The list of possible filters is endless, but some that come with OS/2 are:

MORE
Paginate output
FIND
Search for strings of text
SORT
Sort information by letter or number

The ECHO and TYPE commands are also useful at the start of pipelines.

Use of stream numbers

The stream number can be included, immediately preceding the redirection symbol. So, to redirect the standard input stream for SORT in the example above, we could have used:

SORT 0< ENV.TXT

although the stream number is normally superfluous here since only the value 0 is permitted for redirected input (except in obscure situations, see below). More usefully, we could send standard error and standard output to different places:

SORT < ENV.TXT 1> SORTOUT.TXT 2> SORTERR.TXT

One last thing. It is quite common to redirect standard output to a file, and leave standard error going to the screen. However, sometimes it's useful to run a program completely silently, and you then want to send all output (standard output and standard error) to the same place. This causes a conflict, which is resolved by redirecting one stream directly to the other, then redirecting that stream to the desired output file. This requires us to have a name for the stream to which we are redirecting, so that we can use it after the appropriate > symbol. The syntax for a stream name is somewhat arcane, and it uses the ampersand (&) symbol. A stream name is simply the ampersand followed by the stream number, so standard output is called &1 and standard error is called &2. To avoid ambiguity, there must be no space between the > and the &. This example shows standard error being directed to standard output, and standard output being directed to the file SORTALL.TXT:

SORT < ENV.TXT 2>&1 > SORTALL.TXT

It is advisable to redirect standard error to standard output (and then redirect standard output wherever you want), rather than the other way round. Some programs will not produce the expected effect otherwise.

Advanced topics

Skip this unless you really, really want to know!

You can actually use numbers other than 0, 1 and 2. This requires the program concerned to have opened a stream with the right number; if the program hasn't done so, you'll get an error message. This facility is rarely if ever used.

Programs can also reassign the use of each stream, so stream 0 might become an output stream. In that case, use of the sequence 0 followed by > might have a practical meaning.

Multiple commands on one line

This feature has been in CMD.EXE for many years, but a lot of users are unaware of its existence! Very simply, you are allowed to type more than one OS/2 command on the same line should you wish to do so, and these commands are executed in sequence, subject to certain rules.

The simplest case is the unconditional command sequence. Here, multiple commands are separated by a single ampersand (&) character, and are just executed one after the other:

DIR \OS2 & DIR \OS2\BOOT

However, there might be a problem if the second command depends on the first, and the first command fails. For example, this sequence might be dangerous:

CD \TEMP & DEL *.EXE

especially if, for example, the \TEMP directory did not exist and the current directory was \OS2   ...!!

To make command sequences such as this safer, you can use a conditional command sequence. In such a sequence, commands are executed conditionally depending on the success or failure of previous commands. In the above case, we would want to use the conditional (on success) sequence, in which a command is executed only if its predecessor was successful. Such a sequence has the commands separated by a double ampersand (&&). The previous (dangerous) example becomes:

CD \TEMP && DEL *.EXE

Now, the DEL command is executed only if the CD command is successful.

There may be a situation in which you want a command to be executed only if its predecessor fails. For example, you might wish to copy the file \OS2\BOOT\CONFIG.M to diskette, but it it could not be found, copy \OS2\BOOT\CONFIG.X to the diskette in its place. To do so, you would use the conditional (on failure) sequence, in which the commands are separated by a double vertical bar (||). This command sequence would thus do the job:

COPY \OS2\BOOT\CONFIG.M A:\CONFIG.BAK || COPY \OS2\BOOT\CONFIG.X A:\CONFIG.BAK

Grouping commands

Sometimes multiple commands don't have quite the right effect, particularly when redirection is involved. Consider the following command:

DIR \OS2 & DIR \OS2\BOOT > OS2LIST.TXT

One might have hoped that both directory listings would be sent to OS2LIST.TXT, but the & character effectively splits the line into two independent commands. Thus, the output of the first DIR goes to the screen, and the output of the second DIR goes to the file. This can be fixed by grouping the commands together in parentheses, and redirecting the output of the combined command, as follows:

(DIR \OS2 & DIR \OS2\BOOT) > OS2LIST.TXT

Enclosing filenames

Commands normally consist of a series of items separated by spaces (and certain other characters). Since some OS/2 file systems (e.g. HPFS and JFS) allow spaces within filenames, it could prove difficult to specify such filenames as command parameters.

This problem is addressed by the use of double quotes round filenames. These cause the spaces to be ignored for the purposes of separating command parameters, and allow the complete filename (without the enclosing quotes) to be passed to programs as a single parameter.

For example, suppose that a file is named TEST FILE. If this was to be copied to another file named FILE2, the command would normally be:

COPY TEST FILE FILE2

To CMD.EXE. this looks just like a call to the COPY command (asking to copy TEST to FILE), but with an extra parameter. This would fail. The solution is to use:

COPY "TEST FILE" FILE2

which passes TEST FILE as the first parameter, and FILE2 as the second parameter. This will succeed.

Use of special symbols within commands

It might be necessary to pass parameters to a program, where the parameters include one of the special symbols. In this situation, it is necessary to tell CMD.EXE that the symbol is not to be treated specially. This is achieved by preceding the symbol with the special symbol ^ (the caret character). It naturally follows that, to pass a caret to a program, two must be typed. For example, to pass the string V&A to the program MUSEUM, type:

MUSEUM V^&A

If this were not done, the command would be taken as a call on a program called V followed by a call on a program called A.

Note that the ^ symbol will not work in the case of the special symbol %. If it is necessary to use % in a command line, it must be written as %%.


Back to Tavi OS/2 main page


Last Updated: 19th February 2006
© 2006 by Bob Eager, Tavi Systems