- 论坛徽章:
- 0
|
我前几天恰好写过一个类似的东西,http://www.icylife.net/yunshu/show.php?id=647。
- #!/usr/bin/perl
- use strict;
- use warnings;
- use threads;
- use threads::shared;
- use Thread::Semaphore;
- my ($size, $dircnt, $filecnt) = (0, 0, 0);
- my %size_hash : shared;
- my @sub_dirs;
- if( @ARGV != 3 )
- {
- print "usage: $0 <rootdir> <depth> <topn> \n";
- print "example:$0 c:\\ 3 15\n";
- exit;
- }
- my $root = $ARGV[0];
- my $sub = $ARGV[1];
- my $topn = $ARGV[2];
- if( $root !~ /\\$/ && $root !~ /\/$/ )
- {
- $root = $root."\\";
- }
- print "开始搜寻$root下面的$sub级子目录.....\n";
- &GetSubDirectory( );
- print "开始获取目录大小......\n";
- my $max_thread_count = 100;
- my $semaphore = new Thread::Semaphore( $max_thread_count );
- foreach my $tmp_dir( @sub_dirs )
- {
- $semaphore->down( );
- my $thread = threads->create( \&GetDirectorySize, $tmp_dir );
- $thread->detach();
- }
- &Wait2Quit( );
- my $index = 0;
- foreach my $key ( sort { $size_hash{$b} <=> $size_hash{$a} } keys %size_hash)
- {
- if( $index == $topn )
- {
- last;
- }
- printf( "%-50s%18s 字节\n", $key, $size_hash{$key} );
- $index ++;
- }
- sub Wait2Quit
- {
- my $num = 0;
- while( $num < $max_thread_count )
- {
- # 尝试获取信号量,当能够获取到最大线程数个信号量时,表示所有线程都结束了
- $semaphore->down( );
- $num ++;
- }
- #print "All $max_thread_count thread quit\n";
- }
- sub GetSubDirectory
- {
- my @dirs;
- push( @dirs, $root );
- my ( $current_dir, $file );
- while ( $current_dir = pop(@dirs) )
- {
- # 根据路径中\或者/的次数,确定当前是几级目录
- #print "processing $current_dir:";
- my $sub_count = 0;
- while( $current_dir=~/\\|\//g )
- {
- $sub_count++;
- }
- #print " $sub_count\n";
- # 等于指定深度的,加入到最终数组中
- if( $sub_count == $sub )
- {
- #print $current_dir."\n";
- push( @sub_dirs, $current_dir );
- next;
- }
- # 过深的目录不予处理
- elsif( $sub_count > $sub )
- {
- next;
- }
- # 目录结尾加上\
- if( $current_dir !~ /\\$/ && $current_dir !~ /\/$/ )
- {
- $current_dir = $current_dir."\\";
- }
- # 路径不足的打开目录,查找子目录
- local *DH;
- if ( !opendir(DH, $current_dir) )
- {
- #print "Cannot opendir $current_dir: $!\n";
- next;
- }
- # 读取文件和子目录列表
- foreach( readdir(DH) )
- {
- # 当前目录和上级目录跳过
- if ($_ eq "." || $_ eq "..")
- {
- next;
- }
- $file = $current_dir.$_;
- if ( !-l $file && -d $file )
- {
- #print "Add $file\n";
- push(@dirs, $file);
- }
- #&process($file);
- }
- closedir(DH);
- }
- }
- sub GetDirectorySize
- {
- my $first_dir = shift;
- $size_hash{ $first_dir } = 0;
- my @dirs;
- push( @dirs, $first_dir );
- my ( $current_dir, $file );
- while ( $current_dir = pop(@dirs) )
- {
- # 目录结尾加上\
- if( $current_dir !~ /\\$/ && $current_dir !~ /\/$/ )
- {
- $current_dir = $current_dir."\\";
- }
- # 打开目录,查找子目录以及文件
- local *DH;
- if ( !opendir(DH, $current_dir) )
- {
- #print "Cannot opendir $current_dir: $!\n";
- next;
- }
- # 读取文件和子目录列表
- foreach( readdir(DH) )
- {
- # 当前目录和上级目录跳过
- if ($_ eq "." || $_ eq "..")
- {
- next;
- }
-
- # 形成绝对路径
- $file = $current_dir.$_;
- # 处理目录或符号链接
- if ( !-l $file && -d $file )
- {
- push(@dirs, $file);
- }
-
- $size_hash{ $first_dir } += -s $file;
- }
- closedir(DH);
- }
- $semaphore->up( );
- }
复制代码 |
|