41 warn "Exactly one option must be supplied to indicate the required output\n$ok\n@ARGV\n"; |
42 warn "Exactly one option must be supplied to indicate the required output\n$ok\n@ARGV\n"; |
42 usage(); |
43 usage(); |
43 exit(1); |
44 exit(1); |
44 } |
45 } |
45 |
46 |
46 # Use Windows command to list physical volumes on the machine |
47 # Connect to WMI services on this machine (".") |
47 # (No substed drives, or mapped network drives) |
48 my $wmiServices = Win32::OLE->GetObject( "winmgmts:{impersonationLevel=impersonate,(security)}//." ) or die; |
48 my @details = map {chomp;$_} `echo list volume | diskpart`; |
49 # Get list of all volumes (drive letters) |
|
50 my @volumes = Win32::OLE::in($wmiServices->InstancesOf( "Win32_LogicalDisk" )); |
|
51 # Get list of substed drives |
|
52 my %subst = map { (substr $_, 0, 2) => 1 } `subst`; |
|
53 # Filter volumes to remove non-Partitions, and substed drives |
|
54 @volumes = grep { $_->{DriveType} == 3 && !exists $subst{$_->{DeviceID}} } @volumes; |
|
55 # Also remove the system drive (usually C:) unless it's the only drive in the box! |
|
56 @volumes = grep { $_->{DeviceID} ne $ENV{SystemDrive} } @volumes if scalar(@volumes) > 1; |
49 |
57 |
50 my @drives; |
58 die "Unable to find any suitable drives at all\n" unless @volumes; |
51 my %space; |
|
52 my %capacity; |
|
53 for my $driveLine (@details) |
|
54 { |
|
55 # If this line of output is actually about a healthy HD volume... |
|
56 if ($driveLine =~ m{^\s+Volume \d+\s+([A-Z]).*?(Partition|RAID-5)\s+(\d+) ([A-Z]+)\s+Healthy} ) |
|
57 { |
|
58 my ($letter, $capacityValue, $capacityUnit) = ($1, $3, $4); |
|
59 |
|
60 my %multiplier = ( |
|
61 MB => 1000000, |
|
62 GB => 1000000000, |
|
63 TB => 1000000000000, |
|
64 ); |
|
65 |
|
66 if (not exists $multiplier{$capacityUnit}) |
|
67 { |
|
68 warn "Don't know how to interpret $capacityValue $capacityUnit\n"; |
|
69 next; |
|
70 } |
|
71 $capacityValue *= $multiplier{$capacityUnit}; |
|
72 |
|
73 # Ignore the system drive |
|
74 next if ($driveLine =~ m{System\s*$}); |
|
75 |
|
76 # Use dir to get the freespace (bytes) |
|
77 my @bytesFree = grep { s{^.*?(\d+) bytes free\s*$}{$1} } map {chomp;$_} `cmd /c dir /-C /A $letter:\\`; |
|
78 # Take the value from the bottom of the report |
|
79 my $bytesFree = $bytesFree[-1]; |
|
80 |
|
81 # Record info for this volume |
|
82 push @drives, $letter; |
|
83 $space{$bytesFree} = $letter; |
|
84 $capacity{$capacityValue} = $letter; |
|
85 } |
|
86 } |
|
87 |
|
88 die "Unable to find any suitable drives at all\n" unless %space; |
|
89 |
59 |
90 if ($option->{all}) |
60 if ($option->{all}) |
91 { |
61 { |
92 print join ",", map { "$_:" } @drives; |
62 print join ",", map { $_->{DeviceID} } @volumes; |
93 print "\n"; |
63 print "\n"; |
94 exit; |
|
95 } |
64 } |
96 elsif ($option->{capacity}) |
65 elsif ($option->{capacity}) |
97 { |
66 { |
98 # Sort by capacity to find the largest volume and print out the corresponding letter |
67 # Sort by capacity to find the largest volume and print out the corresponding letter |
99 print "$capacity{(reverse sort keys %capacity)[0]}:\n"; |
68 @volumes = reverse sort { $a->{Size} <=> $b->{Size} } @volumes; |
|
69 print "$volumes[0]->{DeviceID}\n"; |
100 } |
70 } |
101 elsif ($option->{space}) |
71 elsif ($option->{space}) |
102 { |
72 { |
103 # Sort by space to find the volume with the largest amount of space and print out the corresponding letter |
73 # Sort by space to find the volume with the largest amount of space and print out the corresponding letter |
104 print "$space{(reverse sort keys %space)[0]}:\n"; |
74 @volumes = reverse sort { $a->{FreeSpace} <=> $b->{FreeSpace} } @volumes; |
|
75 print "$volumes[0]->{DeviceID}\n"; |
105 } |
76 } |
106 |
77 |
107 exit; |
78 exit; |
108 |
79 |
109 sub usage |
80 sub usage |