Run Tcl Scripts Predictably with tclsh8.6
tclsh8.6 turns a Tcl script into something you can run the same way every time, with predictable argument handling built in. You'll finish with a working script, a reliable way to pass it arguments, and a quick check for which interpreter is actually running it. This guide uses the locally installed Tcl 8.6.14 from the tcl and tcl8.6 packages. Allow about 15 minutes if Tcl is already installed.
The route
Jump straight to the step you need, or tick off Done means at the end.
Everything here runs as an ordinary user: no command needs sudo. The examples print values and create one small script in your current directory, so pick a safe working directory before you start.
1. Check the interpreter you will use
Start by resolving the versioned executable and asking Tcl for its patch level:
$ command -v tclsh8.6
/usr/bin/tclsh8.6
$ tclsh8.6 <<'TCL'
puts [info patchlevel]
puts [info nameofexecutable]
TCL
8.6.14
/usr/bin/tclsh8.6
Your path may differ. What matters is that the reported patch level and executable match what your application expects. The unversioned tclsh name gives you the system default; tclsh8.6 pins the major and minor version explicitly.
Checkpoint
If command -v prints nothing, install the distribution's Tcl package through your normal package-management process. Do not guess a path for a shebang.
2. Use the interactive prompt for small checks
Run tclsh8.6 without a file name when you want to try commands interactively:
$ tclsh8.6
% set greeting "hello"
hello
% puts [string toupper $greeting]
HELLO
% exit
The prompt is % . Each result prints as you go: set greeting shows the value, puts prints its own line. Type exit to leave, or send end-of-file with Ctrl-D.
An interactive session reads .tclshrc from your home directory before the first command, on Unix. That file is Tcl code, not shell configuration. If a prompt misbehaves, check it before blaming the command you're testing. A script-file run does not read it automatically.
3. Create and run a script file
Put the logic in a file when you need repeatable behaviour. This one prints the script name, argument count and each argument:
if {$argc == 0} {
puts stderr "usage: $argv0 NAME..."
exit 2
}
puts "script: $argv0"
puts "arguments: $argc"
foreach name $argv {
puts "hello, $name"
}
Save it as greet.tcl, then run it with explicit arguments:
$ tclsh8.6 greet.tcl Ada "Grace Hopper"
script: greet.tcl
arguments: 2
hello, Ada
hello, Grace Hopper
The first non-option argument is the script file. Everything after it lands in the Tcl list argv; argc counts the elements, and argv0 holds the script name you called. Quoting "Grace Hopper" keeps it as one argument. Do not build a command line by pasting together untrusted argument text: pass values as arguments and let Tcl's list handling keep the boundaries straight.
Checkpoint
Run tclsh8.6 greet.tcl. The script should print its usage message to standard error and return status 2:
$ tclsh8.6 greet.tcl
usage: greet.tcl NAME...
$ printf '%s\n' "$?"
2
4. Make a script directly executable
For a local script, use a shebang that names the interpreter you already verified:
#!/usr/bin/tclsh8.6
puts "Tcl patch level: [info patchlevel]"
Then grant execute permission and run it:
$ chmod u+x version.tcl
$ ./version.tcl
Tcl patch level: 8.6.14
chmod u+x changes the file mode, so chmod u-x version.tcl undoes it once you no longer want direct execution. A hard-coded, versioned path is deliberate: it stops a future default interpreter from silently changing the script's runtime. If the path isn't stable across your target machines, invoke it as tclsh8.6 version.tcl instead, or use the portable launcher below.
5. Choose the encoding and portable launcher carefully
The -encoding option tells tclsh how to read the script file. Use it when the file is stored in a known encoding:
$ tclsh8.6 -encoding utf-8 greet.tcl Ada
This only describes the script file's text. It does not convert arbitrary input values or make a wrongly encoded file safe. Keep the editor, repository and launcher agreement explicit.
When the executable's location varies, the manpage documents a three-line Unix launcher:
#!/bin/sh
# the next line restarts using tclsh \
exec tclsh "$0" ${1+"$@"}
The shell reads the third line as an exec; Tcl reads all three lines as comments, because the continued comment joins the launcher lines together. This preserves the original script arguments while finding tclsh through PATH. Check the result with command -v tclsh before relying on a particular Tcl version.
6. Know the defaults that trip people up
tcl_interactiveis 1 or 0. It's1when no script was supplied and standard input is terminal-like, and0for a normal script run. A pipeline or redirected input is not the same as an interactive terminal, so test the value inside Tcl if your program needs to choose a prompt or user-facing output.tcl_prompt1andtcl_prompt2control interactive prompts. The first runs for a complete command; the second runs while a command is incomplete, and if it's unset, no continuation prompt prints. A custom prompt is executable Tcl code, so never copy prompt settings from an untrusted file into a privileged session.- End-of-file or
exitboth stoptclsh. Errors and command results go to standard output and error according to the command being run, so capture both streams when diagnosing a failed batch job.
Done means
- Interpreter confirmed.
tclsh8.6resolves to the intended executable and reports the expected Tcl patch level. - Arguments work. A script runs with quoted arguments and reads them through
argc,argvandargv0. - Missing arguments fail loudly. The no-argument case returns a deliberate non-zero status instead of continuing with missing data.
- Startup behaviour is known. You know whether interactive
.tclshrcstartup applies to the invocation you are using. - Permissions are reversible. Any direct-execution permission change can be undone with
chmod u-x.