As a result of the recent postings on clt, concerning a tcl/tk only file finder for windows, the following is a crude, slow, but working script (which really has a lot of room for improvement), however, it does work; ---- # A little piece of work due to recent discussions on clt # drives.tcl from the tclers Wiki # find from Jeffery Hobbs, from the tcllib, from the Wiki # pp interface etc by Steve Offutt Thursday January 11, 2001 #mapped drives: #from the tcler's Wiki proc drives {} { foreach drive \ [list a b c d e f g h i j k l m n o p q r s t u v w x y z] { if {[catch {file stat ${drive}: dummy}] == 0} { lappend drives $drive } } return $drives } #source drives.tcl set mylist [drives] #just in case we need to know how many set count [llength $mylist] #which it turns out we dont - yet global file_count set file_count "0" set current [pwd] set drv_ltr [string index $current 0] set drive "$drv_ltr:/" proc make_rb { list parent} { global drv_ltr foreach item $list { grid [radiobutton $parent.$item -text [string toupper "$item:"] -variable drv_ltr \ -command {chg_drv} -value [string toupper "$item" ] ] } } proc chg_drv { } { global drive global drv_ltr set drive "$drv_ltr:/" } menu .menubar -type menubar .menubar add cascade -label "File" -menu .menubar.file -underline 0 .menubar add cascade -label "New Search" -menu .menubar.new -underline 0 menu .menubar.file -tearoff 0 .menubar.file add command -label Exit -underline 1 -command { exit} menu .menubar.new -tearoff 0 .menubar.new add command -label Clear -underline 0 -command { clear } . configure -menu .menubar frame .main -bd 1 -relief groove -width 300 -height 300 frame .main.top -bd 2 -relief groove -width 300 -height 150 frame .main.bl -bd 2 -relief flat -width 150 -height 150 frame .main.br -bd 2 -relief flat -width 150 -height 150 listbox .main.br.lb -yscrollcommand ".main.br.scroll set" -selectmode browse \ -xscrollcommand ".main.br.x_scroll set" \ -bg white -width 30 scrollbar .main.br.scroll -command ".main.br.lb yview" scrollbar .main.br.x_scroll -command ".main.br.lb xview" -orient horizontal label .main.bl.label -text "Drives:" label .main.top.label -text "File to find:" entry .main.top.entry -textvariable find_this -width 30 label .main.top.l2 -text "Current directory:" label .main.top.l3 -text [pwd] label .main.top.l4 -text "Drive to search:" entry .main.top.e4 -textvariable drive button .main.top.b1 -text "Search now" -command {search_now} -relief groove label .main.top.l5 -relief flat -textvariable file_count grid .main.top.label .main.top.entry -sticky ew grid .main.top.l2 .main.top.l3 -sticky ew grid .main.top.l4 .main.top.e4 -sticky ew grid .main.top.b1 .main.top.l5 -sticky ew -columnspan 1 grid .main.top -sticky ew -column 0 -columnspan 2 grid .main.bl.label -sticky ew -columnspan 1 make_rb $mylist .main.bl grid .main.bl -sticky news -columnspan 1 -column 0 label .main.br.label -text "Matching files:" grid .main.br.label -sticky ew grid .main.br.lb .main.br.scroll -sticky nsew grid .main.br.x_scroll -sticky snew grid .main.br -sticky news -row 1 -column 1 -columnspan 1 grid .main -columnspan 2 global my_file_list set my_file_list { } namespace eval ::fileutil {} proc ::fileutil::find {{basedir .} {filtercmd {}}} { #another change global files set oldwd [pwd] cd $basedir set cwd [pwd] set filenames [glob -nocomplain * .*] set files {} set filt [string length $filtercmd] # If we don't remove . and .. from the file list, we'll get stuck in an infinite loop foreach special [list "." ".."] { set index [lsearch -exact $filenames $special] set filenames [lreplace $filenames $index $index] } foreach filename $filenames { # Use uplevel to eval the command, not eval, so that variable # substitutions occur in the right context. if {!$filt || [uplevel $filtercmd [list $filename]]} { lappend files [file join $cwd $filename] } if {[file isdirectory $filename]} { set files [concat $files [find $filename $filtercmd]] } } cd $oldwd return $files } # Use like: #::fileutil::find $dir {string equal README} proc search_now { } { global find_this global my_file_list global drive global file_count set dir $drive set my_string "string equal -nocase $find_this" set my_file_list [::fileutil::find $dir $my_string] show_list set file_count [llength $my_file_list] } bind .main.top.entry {search_now} proc show_list { } { global my_file_list foreach item $my_file_list { .main.br.lb insert end $item } } proc clear { } { .main.br.lb delete 0 end .main.top.entry delete 0 end } console hide wm title . "Tk File Finder (windoze)" wm deiconify . focus .main.top.entry ---- The one thing that you can do with this is to build lists of files with varying filenames across different drives. You will have to script a way to export the list for yourself... ;^) ''so'' ---- In order to properly search an NTFS system (where a user might not have permissions on all directories, change the following: In proc ::fileutil::find {{basedir .} {filtercmd {}}} { # assorted commands removed if {![catch [cd $basedir]]} { # assorted commands removed } cd $oldwd return $files } Ryan Casey ---- [LES] Of course it is slow. You'll be a lot better off building and saving a file name list that can be searched later on instead of scanning disks in every search. In my system, whenever [PowerPro] detects lack of mouse and keyboard activity for 30 minutes, it launches my Tcl script to scan all drives and update the list. When I run a search, I'm only searching a flat text-based list, so it is fast. It would be even faster with an [SQLite] database (although the first query within a certain time span always is slow).