TCL: متكرر الدلائل البحث إلى مصدر جميع الملفات .tcl

StackOverflow https://stackoverflow.com/questions/429386

  •  06-07-2019
  •  | 
  •  

سؤال

ولدي بروك TCL الرئيسي الذي مصادر طن من procs TCL أخرى في غيرها من المجلدات والدلائل اللاحقة. على سبيل المثال، في بروك الرئيسي لها:

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

ويبدو نوع من الغباء أن تفعل ذلك بهذه الطريقة عندما أعرف دائما وسوف مصدر كل شيء في folderA وfolderB. هل هناك وظيفة (أو طريقة بسيطة) التي سوف اسمحوا لي أن مجرد مصدر جميع الملفات .tcl في مجلد كامل؟

هل كانت مفيدة؟

المحلول

وبناء على رد ramanman، وهيريس الروتينية التي يعالج المشكلة باستخدام المدمج في الأوامر ملف TCL والذي يعمل هو الطريق شجرة الدليل بشكل متكرر.

# 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
 }

نصائح أخرى

وويحصل تافهة مع tcllib على متن الطائرة:

package require fileutil
foreach file [fileutil::findByPattern $basepath *.tcl] {
    source $file
}

وربما أكثر من ذلك بقليل منصة مستقلة واستخدام builtins الأوامر بدلا من الأنابيب إلى عملية:

foreach script [glob [file join $basepath folderA *.tcl]] {
  source $script
}

وكرر لfolderB.

إذا كان لديك معايير اختيار أكثر صرامة، ولا تقلق حول تشغيل على أي منصات أخرى، وذلك باستخدام الاكتشاف قد يكون أكثر مرونة.

واستنادا إلى الإجابة السابقة، وهذه الصيغة يعالج دورات التي أنشأتها وصلات رمزية وعملية يزيل الملفات المكررة بسبب صلات رمزية أيضا.

# 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]
}

ونفس الفكرة كما schlenk:

package require Tclx
for_recursive_glob scriptName $basepath *.tcl {
    source $scriptName
}

إذا كنت تريد فقط folderA وfolderB وليس مجلدات أخرى تحت $ basepath:

package require Tclx
for_recursive_glob scriptName [list $basepath/folderA $basepath/folderB] *.tcl {
    source $scriptName
}

وهنا هي طريقة واحدة:

set includes [open "|find $basedir -name \*.tcl -print" r]

while { [gets $includes include] >= 0 } {
  source $include
}

close $includes

والجواب من قبل جوزيف بوي يعمل بشكل جيد إلا أنه يتخطى الملفات في المجلد الأول.

والتغيير:   

set directories [list]
إلى:   
set directories [list $directory]

ولإصلاح

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top