Create a directories list with sub-directories

Hi.

I’ve a problem. How can I create a directory list with all
sub-directories and files like this:

  • root
  • folder1
  • filex
  • folder2
  • folderx
  • file1
  • filex
  • filey

At the moment I’ve only a way to read one directory and print the
directories and files therein. But that is not enough. Can anybody help
me or give me a hint where I can helpfull examples?

bye
Dirk Einecke

Hello,

Dirk Einecke wrote:

Hi.

I’ve a problem. How can I create a directory list with all
sub-directories and files like this:

  • root
  • folder1
  • filex
  • folder2
  • folderx
  • file1
  • filex
  • filey

At the moment I’ve only a way to read one directory and print the
directories and files therein. But that is not enough. Can anybody
help me or give me a hint where I can helpfull examples?

To get all those files, simply do

require ‘find’
Find.find(‘.’) {|path| puts path}

emmanuel

=> [“a”, “e”, “a/b”, “a/c”, “a/c/d”, “e/f”]

note that is */ not /

···

il Tue, 23 Mar 2004 12:14:22 +0100, Dirk Einecke dirk.einecke@gmx.de ha scritto::

Hi.

I’ve a problem. How can I create a directory list with all
sub-directories and files like this:

  • root
  • folder1
  • filex
  • folder2
  • folderx
  • file1
  • filex
  • filey

Dir[‘**/*’]

Message-Id: c3p66c$29fo39$1@ID-43561.news.uni-berlin.de
X-Mail-Count: 95603
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040113

I’ve a problem. How can I create a directory list with all
sub-directories and files like this:

  • root
  • folder1
  • filex
  • folder2
  • folderx
  • file1
  • filex
  • filey

At the moment I’ve only a way to read one directory and print the
directories and files therein. But that is not enough. Can anybody help
me or give me a hint where I can helpfull examples?

As others pointed out, you can use the Find module. Its
implementation is pretty short and worth taking a look at. On an
RPM-based system, you’ll find it in:

$ rpm -ql ruby-libs | grep find.rb
/usr/lib/ruby/1.8/find.rb

If you really want to output an indented tree-like view of a directory
along with its subdirectories, then the Find module may not be the
best tool insofar as it produces a “flattened” view of your directory
structure. You’ll have to do some additional work to “unflatten” it
back into a tree structure. Because of this, you may be better off
performing your own directory traversal rather than relying on Find.
Something along the following lines will give you an indented view:

#!/usr/bin/ruby

WSIndent = " "
LinedIndent = "| "
DirIndent = "± "

def dirTree(dir, indent)
files =
dirs =

Dir.foreach(dir) do |ff|
    path = File.join(dir, ff)
    # Note: this doesn't follow symlinks
    if File.directory?(path)
        dirs.push(ff) if  ff[0] != ?.
    else
        files.push(ff)
    end
end

dirs.sort!
files.sort!
fileIndent = indent + (dirs.length > 0 ? LinedIndent: WSIndent)
files.each do |ff|
    puts "#{fileIndent}#{ff}"
end

return if dirs.length == 0

if dirs.length > 1
    nextIndent = indent + LinedIndent
    thisIndent = indent + DirIndent
    dirs[0..-2].each do |dd|
        puts "#{thisIndent}#{dd}/"
        dirTree(File.join(dir, dd), nextIndent)
    end
end
puts "#{indent + DirIndent}#{dirs[-1]}/"
dirTree(File.join(dir, dirs[-1]), indent + WSIndent)

end

ARGV.each do |dd|
puts “+#{dd}”
dirTree(dd, “”)
end

The end ==================================================

The output from this script looks like this (best viewed with a
fixed-width font):

./tree.rb /usr/lib/ruby/1.8/
+/usr/lib/ruby/1.8/

English.rb
Env.rb
base64.rb
benchmark.rb
± bigdecimal/
jacobian.rb
ludcmp.rb
newton.rb
nlsolve.rb
± cgi/

session.rb
± session/
pstore.rb
± date/
format.rb
± dl/
import.rb
struct.rb
types.rb
win32.rb
± drb/
drb.rb
eq.rb
extserv.rb
extservm.rb
± i386-linux-gnu/
bigdecimal.so
config.h
curses.so
dbm.so
± digest/
md5.so
rmd160.so
sha1.so
sha2.so
± io/
wait.so
± racc/
cparse.so
± io/
nonblock.rb

… elided for brevity’s sake …

± webrick/

accesslog.rb
compat.rb
config.rb
cookie.rb
± httpauth/
authenticator.rb
basicauth.rb
digestauth.rb
htdigest.rb
± httpservlet/
abstract.rb
cgi_runner.rb
cgihandler.rb
erbhandler.rb
± xmlrpc/
base64.rb
client.rb
config.rb
create.rb
± yaml/
baseemitter.rb
basenode.rb
constants.rb
dbm.rb

···

On Tuesday 23 March 2004 06:14, Dirk Einecke wrote:

Hi.

Wow! Wonderful! Thanks a lot.
This will help me very much.

bye
Dirk Einecke

Hi.

Vadim Nasardinov wrote:

The output from this script looks like this (best viewed with a
fixed-width font):

/tree.rb /usr/lib/ruby/1.8/
+/usr/lib/ruby/1.8/

English.rb
Env.rb
base64.rb
benchmark.rb
± bigdecimal/
jacobian.rb

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 tried it yesterday but I
can’t get a working solution.

bye
Dirk Einecke

#!/usr/bin/ruby

WSIndent = " "
LinedIndent = "| "
FileIndent = "± "

def filetree(dir, indent)
files =
dirs =

Dir.foreach(dir) do |ff|
    path = File.join(dir, ff)
    if File.directory?(path)
        dirs.push(ff) if  ff[0] != ?.
    else
        files.push(ff)
    end
end

if dirs.length > 0
    dirs.sort!

    lastDirSpecial = false
    dirRange = 0..0
    if files.length > 0
        dirRange = 0..-1            
    elsif dirs.length > 1
        dirRange = 0..-2
        lastDirSpecial = true
    end

    nextIndent = indent + LinedIndent
    thisIndent = indent + FileIndent
    dirs[dirRange].each do |dd|
        puts "#{thisIndent}#{dd}/"
        filetree(File.join(dir, dd), nextIndent)
    end

    if lastDirSpecial
        puts "#{indent + FileIndent}#{dirs[-1]}/"
        filetree(File.join(dir, dirs[-1]), indent + WSIndent)
    end
end

files.sort!
fileIndent = indent + FileIndent
files.each do |ff|
    puts "#{fileIndent}#{ff}"
end

end

ARGV.each do |dd|
puts “+#{dd}”
filetree(dd, “”)
end

···

On Wednesday 24 March 2004 03:44, Dirk Einecke wrote:

X-Mail-Count: 95709
Message-Id: c3rhhs$2bfft5$1@ID-43561.news.uni-berlin.de

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

···

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?

Hi all.

Well - the script is very good and works like a charm. But at the moment
the structure (the indentings) are made with spaces. Now I think about
the possibility to it with HTML list elements like

    and
  • . I
    tried to rewrite the script for it but all my trials failured.

    Can anybody help me with this special problem?

    bye
    Dirk Einecke