#!/usr/bin/perl
# Copyright 2002-2007 Vlado Keselj http://www.cs.dal.ca/~vlado

sub help { print <<"#EOT" }
# Something like Linux command `tree', version $VERSION
#
# On some systems there is no command that would print recursively a
# directory structure like the Linux command `tree', so then this
# script can be used.
#
# Usage: tree [switches] [directories]
#  -c  Print the entry count for each directory
#  -d  List directories only.
#  -h  Print help and exit.
#  -v  Print version of the program and exit.
#EOT

use strict;
use vars qw($VERSION);
$VERSION = sprintf "%d.%d", q$Revision: 1.6 $ =~ /(\d+)/g;

use Getopt::Std;
use vars qw($opt_v $opt_h $opt_c $opt_d);
getopts("vhcd");

if ($opt_v) { print "$VERSION\n"; exit; }
elsif ($opt_h) { &help(); exit; }

while ($#ARGV > -1) {
    local $_ = &dir_tree(shift);
    s/N\n$/\n/ if $opt_d;
    print;
}

sub dir_tree {
    my $dir = shift;
    my $dirbase = $#_ == -1 ? $dir : shift;

    # symbolic link
    if (-l $dir) { return "$dirbase -> ".readlink($dir).($opt_d?'D':'')."\n" }

    return $dirbase.($opt_d?'D':'')."\n" unless -d $dir;

    local ($_, *DIR);
    opendir(DIR, $dir) || die "can't opendir $dir: $!";
    my (@r) = grep {$_} (map { /^\.\.?$/ ? '' : &dir_tree("$dir/$_", $_) } readdir(DIR));
    closedir(DIR);

    my $entrycount = $#r+1;
    my $r = $opt_c ? "$dirbase [$entrycount entries]" : "$dirbase";
    return $r.($opt_d?"N\n":"\n") unless @r; # empty dir
    $r .= "\n";

    while (@r) {
	my $subdirresult = shift @r;
	if ($opt_d) {
	    next if $subdirresult =~ /D$/;
	    $subdirresult =~ s/N\n$/\n/;
	}
	if ($#r == -1) { $subdirresult = "`-- $subdirresult";
			 $subdirresult =~ s/\n(.)/\n    $1/g }
	else           { $subdirresult = "|-- $subdirresult";
			 $subdirresult =~ s/\n(.)/\n|   $1/g }
	$r .= $subdirresult;
    }

    if ($opt_d) { $r =~ s/\n$/N\n/ }
    return $r;
}

__END__
=head1 NAME

tree - Something like Linux command `tree'

=head1 SYNOPIS

  tree [switches] [directories]

=head1 DESCRIPTION

On some systems there is no command that would print recursively a
directory structure like the Linux command `tree', so then this
script can be used.

Usage: tree [switches] [directories]
   -c  Print the entry count for each directory
   -d  List directories only.
   -h  Print help and exit.
   -v  Print version of the program and exit.

=head1 PREREQUISITES

Getopt::Std;

=head1 SCRIPT CATEGORIES

File System Utilities

=head1 README

Something like Linux command `tree'.

=head1 COPYRIGHT

Copyright 2002-7 Vlado Keselj F<http://www.cs.dal.ca/~vlado>

This script is provided "as is" without expressed or implied warranty.
This is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

The latest version can be found at F<http://www.cs.dal.ca/~vlado/srcperl/>.

=cut