There are two commands that provide information about the file system, glob and file. They provide a method to examine and manipulate the files and directories that is virtually indepedent of the operating system. Some subcommands and pieces of information are, however, necessarily system-dependent, as they refer to features of a particular operating system.
glob returns the names of files and subdirectories in a directory. It uses a name matching mechanism similar to the UNIX ls command or the Windows (DOS) dir command, to return a list of names that match a pattern.
file provides three sets of functionality:
| Subcommand | Purpose |
|---|---|
| dirname | Returns directory portion of path |
| extension | Returns file name extension |
| join | Join directories and the file name to one string |
| nativename | Returns the native name of the file/directory |
| rootname | Returns file name without extension |
| split | Split the string into directory and file names |
| tail | Returns filename without directory |
| Subcommand | Purpose |
|---|---|
| atime | Returns time of last access |
| executable | Returns 1 if file is executable by the user |
| exists | Returns 1 if file exists, 0 otherwise |
| isdirectory | Returns 1 if entry is a directory, 0 otherwise |
| isfile | Returns 1 if entry is a regular file, 0 if not |
| lstat | Returns array of file status information |
| mtime | Returns time of last data modification |
| owned | Returns 1 if file is owned by the user |
| readable | Returns 1 if file is readable by the user |
| readlink | Returns name of file pointed to by a symbolic link |
| size | Returns file size in bytes |
| stat | Returns array of file status information |
| type | Returns type of file |
| writable | Returns 1 if file is writeable by the user |
| Subcommand | Purpose |
|---|---|
| copy | Copy a file or a directory |
| delete | Delete a file or a directory |
| mkdir | Create a new directory |
| rename | Rename or move a file or directory |
Between these two commands, a program can obtain most of the information that it needs and can manipulate the files and directories. While retrieving information about what files are present and what properties they have is usually a highly platform-dependent matter, Tcl provides an interface that hides almost all details that are specific to the platform (but are irrelevant to the programmer).
To take advantage of this feature, always manipulate file names via the file join and file split commands and the others in the first category.
For instance to refer to a file in a directory upwards of the current one:
set upfile [file join ".." "myfile.out"] # upfile will have the value "../myfile.out"
(The ".." indicates the "parent directory") Because external commands may not always deal gracefully with the uniform representation that Tcl employs (with forward slashes as directory separators), Tcl also provides a command to turn the string into one that is native to the platform:
# # On Windows the name becomes "..\myfile.out" # set newname [file nativename [file join ".." "myfile.out"]]
Retrieving all the files with extension ".tcl" in the current directory:
set tclfiles [glob *.tcl]
puts "Name - date of last modification"
foreach f $tclfiles {
puts "$f - [clock format [file mtime $f] -format %x]"
}(The clock command turns the number of seconds returned by the file mtime command into a simple date string, like "07/01/2017")
The pattern follows the same matching rules as the string match globbing rules with these exceptions:
Note that the filenames that match pattern are returned in an arbitrary order (that is, do not expect them to be sorted in alphabetical order, for instance).
Note: Because this calls lstat, if name is a symbolic link,the values in varName will refer to the link, not the file that is linked to.(See also the stat subcommand)
Note: The overview given above does not cover all the details of the various subcommands, nor does it list all subcommands. Please check the man pages for these.
#
# Report all the files and subdirectories in the current directory
# For files: show the size
# For directories: show that they _are_ directories
#
set dirs [glob -nocomplain -type d *]
if { [llength $dirs] > 0 } {
puts "Directories:"
foreach d [lsort $dirs] {
puts " $d"
}
} else {
puts "(no subdirectories)"
}
set files [glob -nocomplain -type f *]
if { [llength $files] > 0 } {
puts "Files:"
foreach f [lsort $files] {
puts " [file size $f] - $f (extension: [file extension $f])"
}
} else {
puts "(no files)"
}The output of the above example for an arbitrary directory:
Directories:
CVS
figs
html
latex
pdf
Files:
36 - .cvsignore (extension: .cvsignore)
4 - .tex2page.hdir (extension: .hdir)
461 - Makefile (extension: )
509 - README.txt (extension: .txt)
2708 - refs.bib (extension: .bib)