open
command returns a file descriptor
or file identifier, which is a string. You should, in
general, treat this string as a black box: you never need to look at
it or print it, just sock it away in a variable to be passed as an
argument to other commands.
stdin
; standard output is available as the
file descriptor stdout
, and standard error is available
as the file descriptor stderr
.
rm
program:
exec rm $filename
Extended Tcl has the unlink
command, which takes a
variable number of arguments, which are file names, and removes them.
open
command takes two arguments, a pathname and an
(optional) access type. The pathname can of course be absolute or
relative. open
supports two notations for the access
method: both mimic different C library functions.
If no second argument is given, the default is r
.
r
r+
w
w+
a
a+
RDONLY
, WRONLY
, or
RDWR
must included in the list.
RDONLY
WRONLY
RDWR
APPEND
CREAT
EXCL
CREAT
, generates an error if the
does already exist (exclusive access).
NONBLOCK
TRUNC
NOCTTY
No status code is returned to indicate success or failure: instead, any problems cause an error to be signalled.
Some examples:
# These first two are equivalent: set f [open /usr/dict/words r] set f [open /usr/dict/words] # So are these two: set tmpfile [open /tmp/temporary w] set tmpfile [open /tmp/temporary [list WRONLY CREAT TRUNC]]
The close
command just takes a file descriptor as an
argument; an error is signalled if the file can't be closed or if it
wasn't open.
puts
command takes a file descriptor and a string,
and writes the string to the file with a trailing newline added
(unless the -nonewline option is given). If invoked with only one
argument, the string is written to standard output. These two
commands are equivalent:
puts stdout "Foo" puts "Foo"
gets
is
line-oriented, while read
is block oriented (and suitable
for random access I/O). Extended Tcl adds some other commands:
bsearch
searches a sorted file using binary search, and
lgets
is list-oriented (it reads Tcl lists).
gets
Commandgets
command comes in two flavors. The one-argument
form takes a file descriptor as a parameter and returns the next line
from the file. End of file is indicated as the empty string; since
this is ambiguous, you may want to use the eof
command to
test whether or not end of file actually occurred.
More useful is the two-argument form, in which a variable name is provided as a parameter. In this form the next line read is stored in the named variable, and the length of the line is returned, or -1 or end of file.
In either form, the terminating newline is removed.
Here is a typical use of gets
in a loop to read an entire
file line by line:
set f [open /home/keith/.profile] while {[gets $f line] >= 0} { puts [string length $line] } close $f
read
Commandread
command takes two parameters, a file descriptor
and a count. The second parameter is optional. If provided,
read
reads the next count bytes from the file
(or up to end of file if there are fewer than count bytes
left). The bytes are returned as a string. If the count
argument is not provided, all the rest of the bytes in the file are
read and returned.
bsearch
Commandbsearch
command does a binary search of an open file.
In its simplest form, it takes a file descriptor and a string to
search for, and returns the matching line if found or the empty
string. It also takes an optional variable name like
gets
, in which case it returns a boolean value. (See
TclX(7tcl) for complete details.)
set f [open /usr/dict/words] bsearch $f zygote => zygote bsearch $f framistan => close $f
lgets
Commandlgets
command reads Tcl lists. It takes the same
arguments as gets
, and returns results the same way, but
reads Tcl lists rather than lines.
Its easy to be confused by this command. In particular, the same way
that it's a mistake to treat an arbitrary string as if it were a list,
it's a mistake to use lgets
on a file that wasn't written
full of lists by Tcl.
To write lists to a file in the form that lgets
will
appreciate only requires that proper lists be written to the
file with puts
. In this example, note the newline in the
second list, which illustrates the difference between
lgets
and gets
:
set f [open feh w] puts $f [list 1 2 3 4] puts $f [list foo bar \n baz] close $f set f [open feh r] while {[lgets $f l] >= 0} { puts [llength $l] } close $f
eof
Commandeof
command, which takes a file descriptor
as an argument and returns a true (1) if end of file has been reached,
or false (0) otherwise. Here is an alternate way to read all lines
from a file, using eof:
set f [open /home/keith/.profile] while {![eof $f]} { puts [string length [gets $f]] } close $f
seek
to set
the file pointer; tell
to read it; and read
to read a record. Note that any command that reads from a file can be
used in a random access fashion; read
just usually makes
more sense than gets
.
seek fd offset ?origin?The
seek
command positions the file pointer for a given
file descriptor fd to a specified byte offset.
By default the offset is relative to the beginning of the
file, but the optional origin parameter can be used to
specify one of:
start
(the beginning of the file)
current
(the current file pointer)
end
(the end of the file)seek
always returns the empty string, so the only way to
tell whether or not the seek suceeded is to use the tell
command and check if you got to where you were going. This is a
Tcl design bug, especially given that the Unix seek system call
returns the status.
Here is some code that reads a file of 80-column card images:
# Return the number of records of size $size in $fd proc number-of-records {size fd} { # Save current file pointer set fp [tell $fd] # Seek to eof seek $fd 0 end # Store file pointer set end [tell $fd] # Restore current file pointer seek $fd $fp if [expr $end % $size != 0] { error "not an integral number of records" } else { expr $end / $size } } set f [open cards] for {set n [number-of-records 80 $f]} {$n > 0} {incr n -1} { puts [string length [read $f 80]] } close $f
tell fdThe
tell
command returns the current position of the file
pointer for file descriptor fd as an integer.
flush fdBy default, files opened for writing by Tcl are block buffered. You can actually control the buffering with Extended Tcl commands, but the simplest approach is to use the flush command after a write. Flushing is generally unnecessary when working with files (and in fact will slow you down), but it's crucial when doing IPC.
cd ?dirname? pwdThe
cd
command changes the current working directory
(CWD) of the Tcl process to dirname (or to the user's home
directory if dirname isn't given). The pwd
command returns the CWD as a string result.
globThe?-nocomplain?
?--?
pattern ?pattern ...?
glob
command provides easy access to the contents of
directories. It takes the same glob
patterns that we've seen before (e.g., in the switch
command) and applies them to the filenames stored in a directory,
returning a list of the filenames that match. If there are no
matching filenames, an error is signalled (unless
-nocomplain
is specified). If the patterns
are specified as absolute pathnames, the returned filenames will be
absolute as well.
file
Commandfile
command gathers a number of miscellaneous file
manipulation commands in one place. There are commands for
manipulating file names, for checking the existance of a file, and for
querying the inode.
file dirname name file extension name file rootname name file tail nameWhile Unix doesn't use mandatory filename extensions in the manner of MS/DOS, extensions are used conventionally, and so Tcl provides commands to manipulate them easily. A picture is worth a thousand words:
file dirname /a/b/foo.html => /a/b file extension /a/b/foo.html => .html file rootname /a/b/foo.html => /a/b/foo file tail /a/b/foo.html => foo.html
file exists name file owned name file executable name file readable name file writable name file isfile name file isdirectory nameThe
file
command provides several predicates for testing
files. All return a Boolean (1 or 0) value. file
readable
, file writable
, and file
owned
test relative to the user running the Tcl script.
file stat name arrayname file type nameThe
file stat
command reads the inode for name
and populates the array variable arrayname with entries for
each field in the inode.
The fields of the inode are named as follows:
nlink
uid
gid
mode
size
atime
mtime
ctime
ino
dev
The file type
command returns a string which represents
the type of the file, one of: file
,
directory
, characterSpecial
,
blockSpecial
, fifo
, link
, or
socket
.
fstat fd fstat fd item fstat fd stat arrayvarExtended Tcl provides access to the contents of inodes via the
fstat
command. This command duplicates the file
stat
command, except that while file stat
operates
on a named file, fstat
operates on a file descriptor.
fstat
comes in three flavors, each taking a
mandatory file descriptor argument. In the first form, with no
additional arguments, all the fields of the inode are returned as a
keyed list. In the second form, only a specific value for the named
field is returned, as a string. In the third form, all the fields are
entered into the named array variable.
The fields of the inode are named as in the file stat
command; the following extra fields are provided:
type
file
,
directory
, characterSpecial
,
blockSpecial
, fifo
, link
, and
socket
.
tty
remotehost