Tcl: Copy all files in directory structure to a single location outside

Viewed 41

I need to recursively find all files that end with .vhd inside a directory and then copy all of them to the directory where the tcl script has been called from. This is the same directory that the user is in when the TCL script is invoked.

So what I need to so to find all .vhd files recursively and regardless of where they are, copy all of them into a single folder. I tried to use glob search but it seems perhaps that it cannot do recursive search. How can this be achieved using TCL?

2 Answers

You can use fileutil::findByPattern from tcllib to get the file names and copy them in a loop:

#!/usr/bin/env tclsh
package require fileutil

proc copy_tree {from_dir pat to_dir} {
    foreach f [::fileutil::findByPattern $from_dir -glob -- $pat] {
        file copy -force -- $f $to_dir
    }
}

copy_tree some/dir *.vhd destination/

Unless you can provide for a tcllib installation for your environment, you will have to implement the directory traversal yourself. Below is but one of the many options (adapted from ftw_4 at Tclers' Wiki; this assumes Tcl 8.5+):

proc copy_tree {from_dirs pat to_dir} {
  set files [list]
  while {[llength $from_dirs]} {
    set from_dirs [lassign $from_dirs name]
    set from_dirs [list {*}[glob -nocomplain -directory $name -type d *] {*}$from_dirs]
    lappend files {*}[glob -nocomplain -directory $name -type f $pat]
  }

  if {[llength $files]} {
    file copy -force -- {*}$files $to_dir
  }
}

Some remarks: This implements an iterative, depth-first directory traversal, and

  • glob is used twice, once to collect sub-directories, once to collect the source files.
  • file copy is executed just once (for the entire collection of source files), not for every source file.
  • The -nocomplain flag on glob is convenient, but maybe not useful in your scenario (whatever that might be).
Related