TCL : 모든 .tcl 파일을 소스하기 위해 Subdirectories를 재귀 적으로 검색합니다.

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

  •  06-07-2019
  •  | 
  •  

문제

다른 폴더와 후속 하위 디렉토리에서 수많은 다른 TCL Procs를 공급하는 메인 TCL Proc가 있습니다. 예를 들어, 메인 Proc에서는 다음과 같습니다.

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

그리고 내가 항상 폴더라와 폴더 브의 모든 것을 소싱 할 것이라는 것을 항상 알고있을 때 그렇게하는 것은 어리석은 것 같습니다. 전체 폴더에 모든 .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
}

아마도 프로세스에 배관하는 대신 독립적이고 Buildins 명령을 사용하는 것입니다.

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
}

폴더라 및 폴더 B를 원한다면 $ 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

Joseph Bui의 답변은 초기 폴더에서 파일을 건너 뛰는 것을 제외하고는 잘 작동합니다.

변화:

set directories [list]
에게:
set directories [list $directory]

고치다

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top