Input And output in Tcl
In this chapter, we will work with input, output operations in Tcl. Tcl has several commands for doing io. We will cover a few of them.Tcl uses objects called channels to read and write data. The channels can be created using the
open
or socket
command. There are three standard channels, which are available to Tcl scripts without explicitly creating them. They are automatically opened by the OS for each new application. They are stdin
, stdout
and stderr
. The standard input, stdin
, is used by the scripts to read data. The standard output, stdout
, is used by scripts to write data. The standard error stderr
is used by scripts to write error messages. In the first example, we will work with the
puts
command. It has the following synopsis: puts ?-nonewline? ?channelId? stringThe channelId is the channel, where we want to write text. The channelId is optional. If not specified, the default stdout is assumed.
$ cat print.tclThe
#!/usr/bin/tclsh
puts "Message 1"
puts stdout "Message 2"
puts stderr "Message 3"
puts
command writes text to the channel. puts "Message 1"If we do not specify the channelId, we write to stdout by default.
puts stdout "Message 2"This line does the same thing as the previous one. We only have explicitly specified the channelId.
puts stderr "Message 3"We write to the standard error channel. The error messages go to the terminal by default.
$ ./print.tclOutput.
Message 1
Message 2
Message 3
In the next example, we will be reading from the standard input channel.
#!/usr/bin/tclshThe script asks for input from the user and then prints a message.
puts -nonewline "Enter your name: "
flush stdout
set name [gets stdin]
puts "Hello $name"
puts -nonewline "Enter your name: "The
puts
command is used to print messages to the terminal. But the command can write to any channel, not just terminal. flush stdoutTcl buffers output internally, so characters written with puts may not appear immediately on the output file or device. We can force output to appear immediately with the
flush
command. set name [gets stdin]The
gets
command reads a line from a channel. $ ./hello.tclSample output of the script.
Enter your name: Jan
Hello Jan
The
read
command is used to read data from the channel. #!/usr/bin/tclshThe script reads a character from the standard input channel and then writes it to the standard output until it encounters a q character.
set c [read stdin 1]
while {$c != "q"} {
puts -nonewline "$c"
set c [read stdin 1]
}
set c [read stdin 1]We read one character from the standard input channel (stdin).
while {$c != "q"} {We continue reading characters until the q is pressed.
Tcl has
pwd
and cd
commands, similar to shell commands. The pwd
command returns the current working directory and the cd
command is used to change the working directory. #!/usr/bin/tclshIn this script, we will print the current working directory. We change the working directory and print the working directory again.
set dir [pwd]
puts $dir
cd ..
set dir [pwd]
puts $dir
set dir [pwd]The
pwd
command returns the current working directory. cd ..We change the working directory to the parent of the current directory. We use the
cd
command. $ ./cwd.tclOutput.
/home/vronskij/programming/tcl/io
/home/vronskij/programming/tcl
Tcl has a
glob
command, which returns the names of the files that match a pattern. #!/usr/bin/tclshThe script prints all files with .tcl extension to the console.
set files [glob *.tcl]
foreach file $files {
puts $file
}
set files [glob *.tcl]The
glob
command returns a list of files that match the *.tcl pattern. foreach file $files {We go through the list of files and print each item of the list to the console.
puts $file
}
$ ./glob.tclAn example from a certain directory.
isfile.tcl
readfile.tcl
attributes.tcl
allfiles.tcl
cwd.tcl
addnumbers.tcl
glob.tcl
write2file.tcl
files.tcl
In the following code example, we are going to check if a file name is a regular file or a directory.
#!/usr/bin/tclshWe go through all file names in the current working directory and print whether it is a file or a directory.
set files [glob *]
foreach fl $files {
if {[file isfile $fl]} {
puts "$fl is a file"
} elseif { [file isdirectory $fl]} {
puts "$fl is a directory"
}
}
set files [glob *]Using the
glob
command we create a list of file and directory names of a current directory. if {[file isfile $fl]} {We execute the body of the if command, if the file name in question is a file.
} elseif { [file isdirectory $fl]} {The
file isdirectory
command determines, whether a file name is a directory. Note that on Unix, a directory is a special case of a file. Next, we are going to write to a file.
#!/usr/bin/tclshIn the script, we open a file for writing. We write days of a week to a file.
set fp [open days w]
set days {Monday Tuesday Wednesday Thursday Friday Saturday Sunday}
puts $fp $days
close $fp
set fp [open days w]We open a file named "days" for writing. The
open
command returns a channel id. set days {Monday Tuesday Wednesday Thursday Friday Saturday Sunday}This data is going to be written to the file.
puts $fp $daysWe used the channel id returned by the
open
command to write to the file. close $fpWe close the opened channel.
$ ./write2file.tclWe run the script and check the contents of the days file.
$ cat days
Monday Tuesday Wednesday Thursday Friday Saturday Sunday
In the following script, we are going to read data from a file.
$ cat languagesWe have a simple file called languages in a directory.
Python
Tcl
Visual Basic
Perl
Java
C
C#
Ruby
Scheme
#!/usr/bin/tclsh
set fp [open languages r]
set data [read $fp]
puts -nonewline $data
close $fp
set fp [open languages r]We create a channel by opening the languages file in a read-only mode.
set data [read $fp]If we do not provide a second parameter to the
read
command, it reads all data from the file until the end of the file. puts -nonewline $dataWe print the data to the console.
$ ./readfile.tclSample run of the readfile.tcl command.
Python
Tcl
Visual Basic
Perl
Java
C
C#
Ruby
Scheme
The next script performs some additional file operations.
#!/usr/bin/tclshWe open a file and write some text to it. The file is copied. The original file is then deleted.
set fp [open newfile w]
puts $fp "this is new file"
flush $fp
file copy newfile newfile2
file delete newfile
close $fp
file copy newfile newfile2The
file copy
command copies a file. file delete newfileThe original file is deleted with the
file delete
command. In the final example, we will work with file attributes.
#!/usr/bin/tclshThe script creates two columns. In the first column, we have the name of the file. In the second column, we display the size of the file.
set files [glob *]
set mx 0
foreach fl $files {
set len [string length $fl]
if { $len > $mx} {
set mx $len
}
}
set fstr "%-$mx\s %-s"
puts [format $fstr Name Size]
set fstr "%-$mx\s %d bytes"
foreach fl $files {
set size [file size $fl]
puts [format $fstr $fl $size]
}
foreach fl $files {In this loop, we find out the most lengthy file name. This will be used when formatting the output columns.
set len [string length $fl]
if { $len > $mx} {
set mx $len
}
}
set fstr "%-$mx\s %-s"Here we print the headers of the columns. To format the data, we use the
puts [format $fstr Name Size]
format
command. set fstr "%-$mx\s %d bytes"We go through the list of files and print each file name and its size. The
foreach fl $files {
set size [file size $fl]
puts [format $fstr $fl $size]
}
file size
command determines the size of the file. $ ./attributes.tclSample run.
Name Size
isfile.tcl 219 bytes
readfile.tcl 98 bytes
tmp 4096 bytes
attributes.tcl 337 bytes
allfiles.tcl 75 bytes
read.tcl~ 114 bytes
cwd.tcl 76 bytes
In this chapter, we have covered Input/Output operations in Tcl.
Do you like this Tutorial? Please link back to this article by copying one of the codes below.
URL: HTML link code: BB (forum) link code:
No comments: