smart - tcl tv reviews
TCL: busca recursivamente subdirectorios para obtener todos los archivos.tcl (7)
Aquí hay una manera:
set includes [open "|find $basedir -name /*.tcl -print" r]
while { [gets $includes include] >= 0 } {
source $include
}
close $includes
Tengo un proc TCL principal que fuentes toneladas de otros procesos tcl en otras carpetas y subdirectorios posteriores. Por ejemplo, en el proceso principal tiene:
source $basepath/folderA/1A.tcl
source $basepath/folderA/2A.tcl
source $basepath/folderA/3A.tcl
source $basepath/folderB/1B.tcl
source $basepath/folderB/2B.tcl
source $basepath/folderB/3B.tcl
y parece algo estúpido hacerlo de esa manera cuando siempre sé que voy a buscar todo en la carpeta A y en la carpeta B. ¿Hay alguna función (o simple) que me permita obtener todos los archivos .tcl en una carpeta completa?
Tal vez un poco más independiente de la plataforma y el uso de comandos incorporados en lugar de conectarse a un proceso:
foreach script [glob [file join $basepath folderA *.tcl]] {
source $script
}
Repita para la carpeta B.
Si tiene criterios de selección más estrictos y no se preocupa de ejecutar en ninguna otra plataforma, el uso de find puede ser más flexible.
Sobre la base de la respuesta de Ramanman, aquí hay una rutina que aborda el problema utilizando los comandos de archivo TCL incorporados y que funciona en el árbol de directorios recursivamente.
# findFiles
# basedir - the directory to start looking in
# pattern - A pattern, as defined by the glob command, that the files must match
proc findFiles { basedir pattern } {
# Fix the directory name, this ensures the directory name is in the
# native format for the platform and contains a final directory seperator
set basedir [string trimright [file join [file normalize $basedir] { }]]
set fileList {}
# Look in the current directory for matching files, -type {f r}
# means ony readable normal files are looked at, -nocomplain stops
# an error being thrown if the returned list is empty
foreach fileName [glob -nocomplain -type {f r} -path $basedir $pattern] {
lappend fileList $fileName
}
# Now look for any sub direcories in the current directory
foreach dirName [glob -nocomplain -type {d r} -path $basedir *] {
# Recusively call the routine on the sub directory and append any
# new files to the results
set subDirList [findFiles $dirName $pattern]
if { [llength $subDirList] > 0 } {
foreach subDirFile $subDirList {
lappend fileList $subDirFile
}
}
}
return $fileList
}
Según una respuesta anterior, esta versión maneja ciclos creados por enlaces simbólicos y en el proceso elimina también archivos duplicados debido a enlaces simbólicos.
# findFiles
# basedir - the directory to start looking in
# pattern - A pattern, as defined by the glob command, that the files must match
proc findFiles {directory pattern} {
# Fix the directory name, this ensures the directory name is in the
# native format for the platform and contains a final directory seperator
set directory [string trimright [file join [file normalize $directory] { }]]
# Starting with the passed in directory, do a breadth first search for
# subdirectories. Avoid cycles by normalizing all file paths and checking
# for duplicates at each level.
set directories [list]
set parents $directory
while {[llength $parents] > 0} {
# Find all the children at the current level
set children [list]
foreach parent $parents {
set children [concat $children [glob -nocomplain -type {d r} -path $parent *]]
}
# Normalize the children
set length [llength $children]
for {set i 0} {$i < $length} {incr i} {
lset children $i [string trimright [file join [file normalize [lindex $children $i]] { }]]
}
# Make the list of children unique
set children [lsort -unique $children]
# Find the children that are not duplicates, use them for the next level
set parents [list]
foreach child $children {
if {[lsearch -sorted $directories $child] == -1} {
lappend parents $child
}
}
# Append the next level directories to the complete list
set directories [lsort -unique [concat $directories $parents]]
}
# Get all the files in the passed in directory and all its subdirectories
set result [list]
foreach directory $directories {
set result [concat $result [glob -nocomplain -type {f r} -path $directory -- $pattern]]
}
# Normalize the filenames
set length [llength $result]
for {set i 0} {$i < $length} {incr i} {
lset result $i [file normalize [lindex $result $i]]
}
# Return only unique filenames
return [lsort -unique $result]
}
Se pone trivial con tcllib a bordo:
package require fileutil
foreach file [fileutil::findByPattern $basepath *.tcl] {
source $file
}
La misma idea que schlenk:
package require Tclx
for_recursive_glob scriptName $basepath *.tcl {
source $scriptName
}
Si solo desea la carpeta A y la carpeta B y no otras carpetas en $ basepath:
package require Tclx
for_recursive_glob scriptName [list $basepath/folderA $basepath/folderB] *.tcl {
source $scriptName
}
La respuesta de Joseph Bui funciona bien, excepto que omite archivos en la carpeta inicial.
Cambio:
set directories [list] A:
set directories [list $directory]
arreglar