Tcl Programming/Working with files

< Tcl Programming

Files and channels

In addition to the functionalities known from C's stdio, Tcl offers more commands that deal with files, similar to what shells provide, though often a bit more verbose. Here are some examples:

glob *.tcl

List all files in the current directory that match the pattern *.tcl.

file copy /from/path/file.ext /to/path
.
file delete /from/path/file.ext
.
file rename before.txt after.txt
.
cd /an/other/directory
.
pwd

To let code temporarily execute in another directory, use this pattern:

set here [pwd]
cd $someotherdir
#... code here
cd $here

More precisely, many "file" operations work in general on "channels", which can be

File names

Files are often addressed with path names, which indicate their position in the directory tree. Like Unix, Tcl uses "/" as path separator, while on Windows "\" is the native way - which brings trouble not only to Tcl, but even to C, because "\" is the escape character on both, so that e.g. \t is parsed as horizontal tab, \n as newline, etc. Fortunately Windows accepts natively "/" as well, so you can use forward slash in both Tcl and C programs as path separator without worries. However, you still have to take care of escape sequences. One stopgap measure is

But Tcl allows to use the "normal" separator / in almost all situations, so you're safer off with that. Unfortunately, things are sad for Mac users, since MacOS (before X) accepts only ":" as file separator.

If you need to, here's ways to convert between the two forms:

% file normalize \\foo\\bar\\grill.txt
C:/foo/bar/grill.txt
% file nativename /foo/bar/grill.txt
\foo\bar\grill.txt

You can even use file join command: file join arg1 arg2 ... argN

Tcl will then take care of all platform dependent details to create platform independent path. For example:

set somepath [file join foo bar grill.txt]

will result in following path (on windows machine): foo/bar/grill.txt

Input and output

Tcl's input/output commands are pretty closely based on those from C's stdio (just strip off the leading f):

C's printf functionality is split in two steps:

puts $handle [format "%05d %s" $number $text]

To process a text file line by line, you have two choices. If the file is smaller than several megabytes, you can read it just in one go:

set f [open $filename]
foreach line [split [read $f] \n] {
    # work with $line here ...
}
close $f

For files of any big size, you can read the lines one by one (though this is slightly slower than the above approach):

set f [open $filename]
while {[gets $f line] >= 0} {
    # work with $line here ...
}
close $f

Finally, if you can format your file so that it is executable Tcl code, the following reading method is fastest:

source $filename

To "touch a file", i.e. create it if not exists, and in any case update its modification time, you can use this:

proc touch name {close [open $name a]}

"Binary" files

All files are made of bytes, which are made of bits, which are binary. The term "binary" with files relates mostly to the fact that they can contain bytes of any value, and line-ends (Carriage Return+Newline in the DOS/Windows world) are not to be translated. Tcl can handle "binary" files without a problem -- just configure the channel as binary after opening:

set fp [open tmp.jpg]
fconfigure $fp -translation binary
set content [read $fp]
close $fp

Now the variable content holds the file's contents, byte for byte.

To test whether a file is "binary", in the sense that it contains NUL bytes:

proc binary? filename {
   set f [open $filename]
   set data [read $f 1024]
   close $f
   expr {[string first \x00 $data]>=0}
}

The file command

Many useful operations with files are collected in the file command. The first argument tells which operation to do:

This article is issued from Wikibooks. The text is licensed under Creative Commons - Attribution - Sharealike. Additional terms may apply for the media files.