Previous section   Next section

Practical Programming in Tcl & Tk, Third Edition
By Brent B. Welch

Table of Contents
Chapter 9.  Working with Files and Programs

Running Programs with exec

The exec command runs programs from your Tcl script.[*] For example:

[*] Unlike other UNIX shell exec commands, the Tcl exec does not replace the current process with the new one. Instead, the Tcl library forks first and executes the program as a child process.

set d [exec date]

The standard output of the program is returned as the value of the exec command. However, if the program writes to its standard error channel or exits with a nonzero status code, then exec raises an error. If you do not care about the exit status, or you use a program that insists on writing to standard error, then you can use catch to mask the errors:

catch {exec program arg arg} result

The exec command supports a full set of I/O redirection and pipeline syntax. Each process normally has three I/O channels associated with it: standard input, standard output, and standard error. With I/O redirection, you can divert these I/O channels to files or to I/O channels you have opened with the Tcl open command. A pipeline is a chain of processes that have the standard output of one command hooked up to the standard input of the next command in the pipeline. Any number of programs can be linked together into a pipeline.

Example 9-1 Using exec on a process pipeline.
set n [exec sort < /etc/passwd | uniq | wc -l 2> /dev/null]

Example 9-1 uses exec to run three programs in a pipeline. The first program is sort, which takes its input from the file /etc/passwd. The output of sort is piped into uniq, which suppresses duplicate lines. The output of uniq is piped into wc, which counts the lines. The error output of the command is diverted to the null device to suppress any error messages. Table 9-1 provides a summary of the syntax understood by the exec command.

Table 9-1. Summary of the exec syntax for I/O redirection.


(First argument.) Do not discard trailing newline from the result.
|Pipes standard output from one process into another.
|&Pipes both standard output and standard error output.
< fileNameTakes input from the named file.
<@ fileIdTakes input from the I/O channel identified by fileId.
<< valueTakes input from the given value.
> fileNameOverwrites fileName with standard output.
2> fileNameOverwrites fileName with standard error output.
>& fileNameOverwrites fileName with both standard error and standard out.
>> fileNameAppends standard output to the named file.
2>> fileNameAppends standard error to the named file.
>>& fileNameAppends both standard error and standard output to the named file.
>@ fileIdDirects standard output to the I/O channel identified by fileId.
2>@ fileIdDirects standard error to the I/O channel identified by fileId.
>&@ fileIdDirects both standard error and standard output to the I/O channel.
&As the last argument, indicates pipeline should run in background.

A trailing & causes the program to run in the background. In this case, the process identifier is returned by the exec command. Otherwise, the exec command blocks during execution of the program, and the standard output of the program is the return value of exec. The trailing newline in the output is trimmed off, unless you specify -keepnewline as the first argument to exec.

If you look closely at the I/O redirection syntax, you'll see that it is built up from a few basic building blocks. The basic idea is that | stands for pipeline, > for output, and < for input. The standard error is joined to the standard output by &. Standard error is diverted separately by using 2>. You can use your own I/O channels by using @.

The auto_noexec Variable

The Tcl shell programs are set up during interactive use to attempt to execute unknown Tcl commands as programs. For example, you can get a directory listing by typing:


instead of:

exec ls

This is handy if you are using the Tcl interpreter as a general shell. It can also cause unexpected behavior when you are just playing around. To turn this off, define the auto_noexec variable:

set auto_noexec anything

Limitations of exec on Windows

Windows 3.1 has an unfortunate combination of special cases that stem from console-mode programs, 16-bit programs, and 32-bit programs. In addition, pipes are really just simulated by writing output from one process to a temporary file and then having the next process read from that file. If exec or a process pipeline fails, it is because of a fundamental limitation of Windows. The good news is that Windows 95 and Windows NT cleaned up most of the problems with exec. Windows NT 4.0 is the most robust.

Tcl 8.0p2 was the last release to officially support Windows 3.1. That release includes Tcl1680.dll, which is necessary to work with the win32s subsystem. If you copy that file into the same directory as the other Tcl DLLs, you may be able to use later releases of Tcl on Windows 3.1. However, there is no guarantee this trick will continue to work.

AppleScript on Macintosh

The exec command is not provided on the Macintosh. Tcl ships with an AppleScript extension that lets you control other Macintosh applications. You can find documentation in the AppleScript.html that goes with the distribution. You must use package require to load the AppleScript command:

package require Tclapplescript
AppleScript junk
=> bad option "junk": must be compile, decompile, delete,
execute, info, load, run, or store.

      Previous section   Next section