The PIPE command allows you to perform UNIX style command processing by 
executing multiple DCL commands in a single command line. You can use 
the PIPE command to execute DCL commands in a number of ways:
  - Multiple command execution 
Multiple DCL commands are specified 
  in a single PIPE command and executed sequentially. The syntax for 
  multiple command execution is as follows:
  
    
       
      
PIPE   command-sequence ; command-sequence [; command-sequences]... 
     | 
  
  
 - Conditional command execution 
A command sequence is executed 
  conditionally depending on the execution result of the preceding 
  command sequence. 
Using the following form, command-sequence2 
  executes if, and only if, command-sequence1 succeeds:
  
    
       
      
PIPE   command-sequence1   &&   command-sequence2 
     | 
  
    
Using the following form, command-sequence2 executes if, and only 
    if, command-sequence1 fails:
  
    
       
      
PIPE   command-sequence1   ||   command-sequence2 
     | 
  
  
 - Pipeline command execution 
A pipeline is formed by connecting 
  DCL commands with pipes as follows:
  
    
       
      
PIPE pipeline-segment-command | pipeline-segment-command [|...] 
     | 
  
    
Each pipeline-segment command runs in a separate subprocess with 
    its SYS$OUTPUT connected to the SYS$INPUT of the next pipeline-segment 
    command. These subprocesses execute in parallel; however, they are 
    synchronized to the extent that each pipeline-segment command, except 
    the first, reads the standard output of its predecessor as its standard 
    input. A pipeline finishes execution when the last pipeline-segment 
    command is done. 
It is very common to use filter applications in a 
    pipeline. A filter application is a program that takes data from 
    SYS$INPUT, transforms it in a specific way, and writes it to SYS$OUTPUT.
  
 - Subshell execution 
Command sequences can be executed in a 
  subprocess environment by using the subshell execution form:
  
    
       
      
PIPE   ( command-sequence [separator command-sequence]... ) 
     | 
  
    
The command sequences in a subshell are executed in a subprocess 
    environment. DCL waits for the subshell to complete before executing 
    the next command sequence. The ( ) separator is similar to the 
    SPAWN/WAIT command.
  
 - Background execution 
Command sequences can be executed in a 
  subprocess environment by using the following form:
  
    
       
      
PIPE  command-sequence [ separator command-sequence]...  & 
     | 
  
    
DCL does not wait for the command sequences to finish. Control 
    passes back to DCL once the background subprocess is created.
  
 - Input/output redirection 
A command sequence can redirect its 
  SYS$INPUT, SYS$OUTPUT, or SYS$ERROR to a file during execution of the 
  command as follows: 
To redirect SYS$INPUT:
  
    
       
      
   PIPE    command-sequence < redirected-input-file 
     | 
  
    
To redirect SYS$OUTPUT:
  
    
       
      
   PIPE    command-sequence > redirected-output-file 
     | 
  
    
To redirect SYS$ERROR:
  
    
       
      
   PIPE    command-sequence 2> redirected-error-file 
     | 
  
    
A pipeline-segment command can also redirect its SYS$INPUT, 
    SYS$OUTPUT, or SYS$ERROR; however, SYS$OUTPUT redirection is allowed 
    only for the last pipeline-segment command, and SYS$INPUT redirection 
    is allowed only for the first pipeline-segment command.
 
You can interrupt a PIPE command by pressing Ctrl/Y. If the PIPE 
command is executing in a pipeline or a subshell command sequence, the 
command sequence and the PIPE command are deleted. In this case, a 
CONTINUE command entered immediately after the interrupt will not 
resume the execution of the PIPE command.
If the PIPE command is executing a command sequence other than a 
subshell or a pipeline command sequence, DCL behaves as if the command 
sequence were entered as a DCL command without the PIPE command verb 
and interrupted by Ctrl/Y. See the OpenVMS User's Manual for more information 
on the Ctrl/Y interrupt.
Each command sequence sets the global symbol $STATUS with a returned 
value after it finishes execution. The return status of the PIPE 
command is the return status of the last command performed in 
the last segment. If all segments fail with some kind of error and the 
last segment returns with success, the status returned to DCL is the 
success.
When a PIPE command is executed in a command procedure with the ON 
condition processing, the conditional execution of command sequences 
(&&, ||) takes precedence over the action previously specified 
by the ON condition statement.
DCL Command Restrictions
The PIPE command creates a special execution context for its command 
sequences. The following DCL commands either do not work or exhibit new 
behavior in this context:
  - PIPE --- Nested PIPE commands in the same command procedure level 
  are not allowed. There can only be one PIPE command context for each 
  command procedure level; however, nested PIPE commands at different 
  procedure levels are allowed. For example:
  
    
       
      
 $ TYPE FOO.COM 
 $ ! FOO.COM 
 $   : 
 $ PIPE   ... 
 $ : 
 $ 
 $ PIPE    @FOO.COM ; ... 
 
 | 
    
In this example, the PIPE command inside FOO.COM is allowed because 
    it is executed at a different command procedure level.
   - GOTO and EXIT --- These two commands, when executed as PIPE command 
  sequences, delete the PIPE command context before the GOTO or EXIT 
  command is executed. Any command sequences following these two commands 
  in a PIPE command are flushed.
  
 - STOP --- The STOP command, when executed after a PIPE command is 
  interrupted by Ctrl/Y, deletes the PIPE command context.
  
 - THEN, ELSE, ENDIF, SUBROUTINE, ENDSUBROUTINE, RETURN, and DCL 
  labels --- These commands cannot execute as PIPE command sequences 
  because it is not possible to realize their functions in a PIPE command 
  context.
 
Improving Subprocess Performance
A PIPE command can generate a number of subprocesses during execution. 
Often, the applications invoked by command sequences do not depend on 
the process logical names and symbol names. In this case, the spawning 
of subprocesses can be accelerated by using the /NOLOGICAL_NAMES and 
/NOSYMBOLS qualifiers, which suppress the passing of process logical 
names and symbols to the subprocesses created by the PIPE command.
Input/Output Redirection
DCL users can use the DEFINE or ASSIGN command to redirect SYS$INPUT, 
SYS$OUTPUT, or SYS$ERROR. Such redirection can be created as either the 
user-mode (using the /USER_MODE qualifier) or supervisor-mode (using 
the /SUPERVISOR_MODE qualifier) redirection. A user-mode redirection 
only affects the environment of the next user-mode image.
In a PIPE command, redirection can be achieved by using the redirection 
syntax. A PIPE command redirection is quite different from that created 
by the DEFINE or ASSIGN command, as follows:
  - Redirections are created in supervisor mode. This means that both 
  user-mode applications and DCL commands are affected by the 
  redirections.
  
 - The redirected environment only applies to the command sequence or 
  the pipeline-segment command that specifies the redirection syntax. 
  After the execution of the command sequence or pipeline-segment 
  command, the original process input/output environment (that is, 
  SYS$INPUT, SYS$OUTPUT, and SYS$ERROR) is restored before command 
  execution continues.
 
When SYS$OUTPUT is redirected, the redirected output file is always 
created, whether or not the command sequence actually writes to 
SYS$OUTPUT. If a version of a file with the same name as the redirected 
output file already exists, a new version of that file is created. 
(This behavior is the same as using the DEFINE or ASSIGN command to 
redefine SYS$OUTPUT in supervisor mode.) Note that the redirected file 
is created before the command sequence is executed. If the redirected 
file is also used in the command sequence, the operation may fail, as 
in the following example:
  
    
       
      
$ PIPE SEARCH TRANS.LOG "alpha" > TRANS.LOG
%SEARCH-W-OPENIN, error opening TRANS.LOG;2 as input
-RMS-E-FLK, file currently locked by another user
 
 | 
In this example, a new version of TRANS.LOG is created and opened for 
write access; the SEARCH command then tries to get read access to the 
most recent version of TRANS.LOG instead of the expected previous 
version.
When SYS$ERROR is redirected, the redirected error file is only created 
when the command sequence actually writes to the SYS$ERROR during 
execution, and there is no existing file with the same name as the 
redirected error file. If a file with the same name as the redirected 
error file already exists, that file is opened as the redirected error 
file. The error output generated by this command sequence is then 
appended to the end of the redirected error file. (This behavior is the 
same as using the DEFINE or ASSIGN command to redefine SYS$ERROR in 
supervisor mode.)
Pipelines and TEEs
This section describes aspects of DCL that function differently in the 
context of a pipeline.
Some of the following constructs are used in the implementation of a 
TEE.
Using SYS$COMMAND
The SYS$COMMAND of a subprocess is normally the same as its SYS$INPUT 
(if no command procedures are involved). In a pipeline, however, the 
SYS$COMMAND of a subprocess is set to the SYS$COMMAND of the parent 
process instead of to the preceding pipe (which is the SYS$INPUT of the 
pipeline-segment command).
Using TEEs and SYS$PIPE
In most cases, input from the pipe can be obtained by reading the data 
from SYS$INPUT; however, when a command procedure is invoked as a 
pipeline segment command, SYS$INPUT is redirected to the command 
procedure file. To obtain data from the pipe inside a command 
procedure, the logical SYS$PIPE can be used.
The following is an example of a pipeline DCL application TEE.COM:
  
    
       
      
 $ ! TEE.COM - command procedure to display/log data flowing through 
 $ !           a pipeline 
 $ ! Usage: @TEE log-file 
 $ 
 $ OPEN/WRITE  tee_file 'P1' 
 $ LOOP: 
 $  READ/END_OF_FILE=EXIT  SYS$PIPE LINE 
 $  WRITE SYS$OUTPUT LINE ! Send it out to the next stage of the pipeline 
 $  WRITE tee_file LINE  ! Log output to the log file 
 $  GOTO LOOP 
 $ EXIT: 
 $  CLOSE tee_file 
 $  EXIT 
 
 | 
The PIPE command to use TEE.COM can be:
  
    
       
      
$ PIPE  SHOW SYSTEM | @TEE showsys.log | SEARCH SYS$INPUT LEF 
 
 | 
The command procedure TEE.COM is used to log the data flowing through 
the pipeline. It reads in the data from SYS$PIPE instead of SYS$INPUT.
Image Verification in a Pipeline
In a pipeline, image verification is turned off by default, even when 
the command SET VERIFY=IMAGE is executed before the PIPE command is 
entered. This prevents duplication of data records going through the 
pipeline.
To turn on image verification in a pipeline, an explicit SET 
VERIFY=IMAGE command must precede the pipeline segment command. You can 
use a subshell to do this, as follows:
  
    
       
      
$ PIPE ... | (SET VERIFY=IMAGE ; ...)  | ...
 
 | 
File Access Methods in a Pipeline
A pipeline segment command can only use the RMS sequential file access 
method to read and write to the pipes. Certain OpenVMS utilities may 
access their input and output files using methods other than sequential 
access. These operations are not supported in a pipeline, and will 
fail, as in the following example:
  
    
       
      
$ PIPE CC/NOOBJ/NOLIS TEST.C | SEARCH SYS$INPUT/WIND=(1,1) "%cc-w-"
 
%SEARCH-F-RFAERR, RMS error using RFA access
-RMS-F-RAC, invalid record access mode
 
 | 
In this example, the /WINDOW qualifier for the SEARCH command requires 
the relative file access method.