Notes on using the default OS/2 command processor (CMD.EXE) |
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!
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 |
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 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.TMPIf 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.LSTMore usefully, to generate a file containing the names of all current environment variables:
SET > ENV.TXTIn 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.TXTThe 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 | SORTLastly, to send the sorted output directly to the file SORTENV.TXT:
SET | SORT > SORTENV.TXTYou 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.
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:
The ECHO and TYPE commands are also useful at the start of pipelines.
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.TXTalthough 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.TXTOne 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.TXTIt 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.
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.
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\BOOTHowever, 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 *.EXEespecially 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 *.EXENow, 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.BAKSometimes multiple commands don't have quite the right effect, particularly when redirection is involved. Consider the following command:
DIR \OS2 & DIR \OS2\BOOT > OS2LIST.TXTOne 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.TXTCommands 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 FILE2To 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.
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^&AIf 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 %%.