On Wednesday 24 March 2004 13:32, Vadim Nasardinov wrote: > X-Mail-Count: 95761 > Message-Id: <200403241336.50319 / vadim.nasardinov> > > On Wednesday 24 March 2004 03:44, Dirk Einecke wrote: > > I have one question: With your code the files in a folder will be > > print out at first. Is it possible to change this that the order > > is inverted: at first the folders an after that the files? I needed a variation of the above script that would print out, for each directory, the number of files and subdirectories that it contains directly and indirectly. This turned out to be an interesting opportunity for implementing a fairly simple backtracking tree traversal via callcc. This doesn't quite rise to the level of inclusion in http://blade.nagaokaut.ac.jp/~sinara/ruby/callcc-lib/ but may be interesting to some. Here goes. #!/usr/bin/ruby # Author: Vadim Nasardinov # Since: 2004-03-24 # In a lesser language (how's that for a flamebait?), this would be # coded by explicitly building a tree data structure in the first # pass, and printing it out in the second pass. This script avoids # building the tree explicitly by exploiting the fact that the # necessary tree structure is already maintained implicitly by the # interpreter: the call tree of the file_tree_stats method mirrors the # file tree that we want to print out. def file_tree_stats(dir, indent) dirs = [] n_files = 0 Dir.foreach(dir) do |ff| path = File.join(dir, ff) if File.directory?(path) and ff[0] != ?. dirs.push(path) elsif path[-3..-1] == '.rb' n_files = n_files.succ end end dirs.sort! dirs.reverse! conts = [] first_pass = true n_total_dirs = dirs.length n_total_files = n_files dirs.each do |dd| cont, n_subdirs, n_subfiles = file_tree_stats(dd, indent + " ") break if cont == nil n_total_dirs += n_subdirs n_total_files += n_subfiles conts.push(cont) end if first_pass first_pass = false callcc do |k| return k, n_total_dirs, n_total_files end puts "#{indent}#{File.basename(dir)}/" stats = " #{indent}#{n_files} files" stats += " / #{n_total_files} total files" if n_files != n_total_files if dirs.length > 0 stats += " / #{dirs.length} subdirs" if n_total_dirs > dirs.length stats += " / #{n_total_dirs} total subdirs" end end puts stats end if conts.length > 0 conts.pop.call end end ARGV.each do |dd| k, n_dirs, n_files = file_tree_stats(dd, "") if k != nil puts dd puts "#{n_files} files / #{n_dirs} subdirectories" k.call end end # The end ================================= Example: $ ./file_tree_stats.rb /usr/lib/ruby/1.8 /usr/lib/ruby/1.8 300 files / 41 subdirectories 1.8/ 77 files / 300 total files / 20 subdirs / 41 total subdirs bigdecimal/ 5 files cgi/ 1 files / 2 total files / 1 subdirs session/ 1 files date/ 1 files dl/ 4 files drb/ 9 files i386-linux-gnu/ 1 files / 3 subdirs digest/ 0 files io/ 0 files racc/ 0 files io/ 1 files irb/ 15 files / 31 total files / 3 subdirs / 4 total subdirs cmd/ 6 files ext/ 8 files lc/ 1 files / 2 total files / 1 subdirs ja/ 1 files net/ 11 files openssl/ 6 files optparse/ 4 files racc/ 1 files rexml/ 27 files / 53 total files / 4 subdirs dtd/ 5 files encodings/ 13 files light/ 1 files parsers/ 7 files runit/ 6 files / 7 total files / 1 subdirs cui/ 1 files shell/ 7 files test/ 1 files / 15 total files / 1 subdirs / 6 total subdirs unit/ 7 files / 14 total files / 2 subdirs / 5 total subdirs ui/ 2 files / 5 total files / 3 subdirs console/ 1 files fox/ 1 files gtk/ 1 files util/ 2 files uri/ 7 files webrick/ 19 files / 32 total files / 2 subdirs httpauth/ 7 files httpservlet/ 6 files xmlrpc/ 10 files yaml/ 16 files