ZetCode

Tcl exec Command

last modified October 20, 2026

The Tcl exec command is used to execute external programs. It captures the program's output and returns it as a string. The command is essential for system integration tasks.

Basic Definition

The exec command runs an external program with given arguments. It waits for the program to complete and returns what the program wrote to standard output, without the final newline. The command is not run by a shell, so there is no wildcard, variable or quote processing; only the pipe and redirection operators (|, >, 2>&1 and so on) are understood by exec itself.

Syntax: exec ?switches? arg ?arg ...?. Switches control how the command handles input/output and errors. Arguments form the command line.

Basic Command Execution

This example shows the simplest usage of exec to run a command.

basic_exec.tcl
set result [exec date]
puts "Current date: $result"

This executes the date command and stores its output in the result variable; the trailing newline of the output is removed. The output is then printed to standard output.

Handling Command Output

The exec command raises an error when the program exits with a non-zero status or writes to standard error.

exec_output.tcl
if {[catch {exec ls /nonexistent} result]} {
    puts "Command failed with error: $result"
} else {
    puts "Command output: $result"
}

This attempts to list a nonexistent directory. The ls command writes a message to standard error and exits with status 2, so exec raises an error, and catch handles it. The text the program wrote to standard error becomes the error message. The exit status is available in $::errorCode (CHILDSTATUS pid status). A program that only writes to standard error and exits with 0 also raises an error, unless the error output is redirected with 2>@1 or 2>/dev/null.

Command with Arguments

Each argument of exec becomes one argument of the program, as is, without any shell processing.

exec_args.tcl
set files [exec ls -l /usr/bin]
set first [lrange [split $files \n] 0 4]
puts "First 5 lines of the listing:\n[join $first \n]"

This lists files in /usr/bin and stores the output in the files variable. Only the first 5 lines are shown, which are selected in Tcl rather than with head; a command that is cut short by head is killed by a broken pipe, and exec reports that as an error. Because no shell is involved, a wildcard such as /usr/bin/*.sh would not be expanded; use glob for that.

Redirecting Output

The exec command itself understands output redirection to files.

exec_redirect.tcl
exec ps aux > processes.txt
set size [file size processes.txt]
puts "Process list saved to processes.txt ($size bytes)"

This runs the ps command and redirects its output to a file; the redirection is done by exec, not by a shell. The file size is then checked to confirm the operation succeeded. The size differs from system to system.

Environment Variables

Environment variables for the executed command are set through the global env array.

exec_env.tcl
set ::env(MY_VAR) "Hello World"
set result [exec printenv MY_VAR]
puts "Environment variable value: $result"

This sets a custom environment variable and then uses printenv to verify its value. Changing env changes the environment of the Tcl process itself, and every program started afterwards inherits it; there is no way to set a variable for a single call, except by running the program through env, for example exec env MY_VAR=x printenv MY_VAR.

Command Pipeline

Multiple commands can be chained together using pipes.

exec_pipeline.tcl
set count [exec ps aux | grep tclsh | wc -l]
puts "Number of tclsh processes: $count"

This pipeline counts the lines of the process list that contain "tclsh". The output of each command is piped to the next one in the chain. The count is only approximate: it includes the grep process itself and the script that is running (and, if started through a wrapper, the wrapper's command line). Also, grep exits with status 1 when nothing matches, which makes exec raise an error.

Best Practices

This tutorial covered the Tcl exec command with practical examples showing its usage in different scenarios.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Tcl Tutorials.