use warnings; use strict; use Tk; use Tk::Tree; my $rootPath = shift; ShowHelp () if ! defined $rootPath; ShowHelp (-2, "Error finding folder $rootPath\n\n") if ! -d $rootPath; my $main = MainWindow->new (-title => "Folder stats for $rootPath"); my $tree = $main->ScrlTree ( -font => 'FixedSys 8', -itemtype => 'text', -separator => '/', -scrollbars => "osoe" ); my @pathStack = (1); my $maxNesting = 0; my $totalLines; my $maxLineLength = 0; my $currPath = join "/", @pathStack; $tree->add ($currPath, -text => $rootPath); my ($subDirCount, $subFileCount, $subTotalSize) = buildSubTree ($tree, $rootPath, \@pathStack, \$maxNesting, \$totalLines, \$maxLineLength); my $annotation = $rootPath . " \t("; my $plural = $subDirCount != 1 ? 's' : ''; $annotation .= $subDirCount . " dir$plural, " if $subDirCount; $annotation .= "$subFileCount files, $subTotalSize bytes)"; $tree->entryconfigure ($currPath, -text => $annotation); $totalLines = 40 if $totalLines > 40; $main->geometry (($maxLineLength + @pathStack * 4) * 5 . 'x' . (40 + $totalLines * 20)); closeTree ($tree, ''); $tree->pack(-fill=>'both',-expand => 1); MainLoop; sub closeTree { my $tree = shift; my ($entryPath, $hideChildren) = @_; my @children = $tree->info (children => $entryPath); return if ! @children; for (@children) { closeTree ($tree, $_, 1); $tree->hide ('entry' => $_) if $hideChildren; } $tree->setmode ($entryPath, 'open') if length $entryPath; } sub buildSubTree { my ($tree, $rootPath, $pathStack, $maxNesting, $totalLines, $maxLineLength) = @_; my $dirCount = 0; my $fileCount = 0; my $sizeTotal = 0; push @$pathStack, 1; $$maxNesting = @$pathStack if $$maxNesting < @$pathStack; my $dir; opendir $dir, $rootPath; while (my $currDir = readdir $dir) { next if $currDir =~ /^\.\.?$/; my $path = "$rootPath/$currDir"; ++$$totalLines; my $currPath = join "/", @$pathStack; my $nodeText = $path; $tree->add ($currPath, -text => $nodeText); if (-d $path) { my ($subDirCount, $subFileCount, $subTotalSize) = buildSubTree ($tree, $path, $pathStack, $maxNesting, $totalLines, $maxLineLength); $dirCount += $subDirCount + 1; $fileCount += $subFileCount; $sizeTotal += $subTotalSize; my $annotation = $nodeText . " \t("; my $plural = $subDirCount != 1 ? 's' : ''; $annotation .= $subDirCount . " dir$plural, " if $subDirCount; $annotation .= "$subFileCount files, $subTotalSize bytes)"; $tree->entryconfigure ($currPath, -text => $annotation); } else { my $fileSize = -s $path; $tree->entryconfigure ($currPath, -text => $nodeText . " ($fileSize bytes)"); ++$fileCount; $sizeTotal += $fileSize; } $$maxLineLength = length ($nodeText) if length ($nodeText) > $$maxLineLength; ++$pathStack->[-1]; } closedir $dir; pop @$pathStack; return ($dirCount, $fileCount, $sizeTotal); } sub ShowHelp { my $exitValue = 0; $exitValue = shift if defined $_[0] and $_[0] =~ /^[-+]?\d+$/; print $_ while $_ = shift; print < HELP exit ($exitValue || -1); }