Tcl 如何处理使用fileutil::traverse时被拒绝的权限 问题
我不是Tcl新手,这个问题困扰着我。我想遍历目录树,处理或忽略那些我没有权限访问的子目录或文件。下面是一个小示例代码:Tcl 如何处理使用fileutil::traverse时被拒绝的权限 问题,tcl,Tcl,我不是Tcl新手,这个问题困扰着我。我想遍历目录树,处理或忽略那些我没有权限访问的子目录或文件。下面是一个小示例代码: #!/usr/bin/env tclsh package require fileutil::traverse proc errorHandler {absPath errorMessage} { puts "ERROR: $absPath $errorMessage" } # Main set searchDir /tmp fileutil::traverse
#!/usr/bin/env tclsh
package require fileutil::traverse
proc errorHandler {absPath errorMessage} {
puts "ERROR: $absPath $errorMessage"
}
# Main
set searchDir /tmp
fileutil::traverse t $searchDir -errorcmd errorHandler
puts "\nFiles in $searchDir:"
t foreach fileName {
puts $fileName
}
输出:
...
couldn't read directory "/tmp/launchd-56801.nzZRsA/": permission denied
while executing
"glob -nocomplain -directory $current -types f -- *"
(procedure "GLOBF" line 2)
invoked from within
"GLOBF $top"
(procedure "::fileutil::traverse::Snit_methodnext" line 44)
invoked from within
"$self next currentfile"
(procedure "::fileutil::traverse::Snit_methodforeach" line 11)
invoked from within
"t foreach fileName {
puts $fileName
}"
(file "./traverser1.tcl" line 17)
我知道问题所在:我没有权限阅读一些子目录。这就是为什么我在每个文档中都添加了错误处理程序。但是,从未调用该错误处理程序。我怀疑这是Tcl中的一个bug,但这可能意味着我误解了文档,没有正确使用包。我感谢任何帮助或建议来解决这个问题
我的环境
- Mac OS X Mountain Lion
- Tcl 8.5.9
fileutil::traverse
的源代码。我发现的是:
method next {fvar} {
# code ...
if {![ACCESS $top]} {
Error ...
...
但对于Tcl 8.4或更高版本,ACCESS的实现是:
proc ::fileutil::traverse::ACCESS {args} {return 1}
鉴于Tcl 8.3的实施是:
proc ::fileutil::traverse::ACCESS {current} {
if {[catch {
set h [pwd] ; cd $current ; cd $h
}]} {return 0}
return 1
}
当我用8.3版本替换8.4版本时,一切正常。这告诉我这是代码中的一个bug。我不知道为什么会这样。我找到了一个解决办法,添加了一个预过滤器,它尝试将cd放入目录中,如果目录可以访问,则返回True:
#!/usr/bin/env tclsh
package require fileutil::traverse
# isAccessible: determines if the directory is accessible by attempting to cd into it
proc isAccessible {absPath} {
set currentDir [pwd]
if {[catch {cd $absPath}]} {
set chdirOK False
} else {
set chdirOK True
}
cd $currentDir
return $chdirOK
}
# Main
set searchDir /tmp
fileutil::traverse t $searchDir -prefilter isAccessible
puts "\nFiles in $searchDir:"
t foreach fileName {
puts $fileName
}
更新
多纳尔的建议很好:很有效,很简短,很甜蜜:
proc isAccessible {absPath} {
return [file readable $absPath]
}
我们甚至可以完全取消编写isAccessible
:
fileutil::traverse t $searchDir -prefilter "file readable"
阅读文档时,errorHandler进程是否应该返回false?我已经尝试了两种方法:返回false,然后返回True。这没什么区别。