Piping Operating System Commands
The usual method of issuing an operating system command is via the X statement (or a similar facility such as CALL SYSTEM, %SYSEXEC or SYSTASK). However an interesting alternative is to put the command into a FILENAME PIPE. Normally one would only think of using this approach when the output from the command was always going to be of interest, for example with a “dir” command. However it can also be used in cases where the output is only of interest when things go wrong.
As an example, consider using a Windows command to delete a file, and suppose it is required to put a warning in the log if the file does not exist. Here is a macro that does this.
The macro is invoked twice to delete the same file. It succeeds only on the first occasion, and the log shows:
In the FILENAME PIPE statement, the command is followed by “2>&&1”, which redirects standard error to standard output. This means that any error lines that may result will be read by the INPUT statement in the data step. (Without this redirection, the lines would reach the SAS log, but not the data step.)
The INPUT statement here will only find anything to read if there are error lines. The data step is coded so that, if there is more than one error line, only the first will be prefixed with “WARNING:”. (Early versions of SAS did not allow the _INFILE_ buffer to be manipulated in this way, but it has been a legitimate operation for quite a while now.) A line beginning with “WARNING:” that is PUT to the log is coloured by SAS just as if it had generated the message itself. (The same applies to lines beginning with “ERROR:” or “NOTE:”.)
The data step would normally produce a note in the log about the number of lines read from the pipe. The macro suppresses this by specifying OPTIONS NONOTES, but before doing so it uses the GETOPTION function to save the current value of the NOTES option (which will be either “NOTES” or “NONOTES”). After the data step, that value is restored.
The OS_CMD macro is intended to be called from open code. The next macro does the same thing, but is intended for use within a data step.
Macro OS_CMD_IN_STEP builds up, in a buffer called _CODESTR, an invocation of the OS_CMD macro. It then issues this command using the DOSUBL function. Notice that OS_CMD is going to be running an entire data step of its own, within the main data step; that’s fine – it’s what DOSUBL is for. And this data step will indeed delete the file - or write a warning message to the SAS log if it does not exist.