Here's a utility I have to thoroughly clean my windows machines of temporary files, and then email a report on what it did.... Nothing very clever in here, but may help someone with the same need, or passion for keeping tidy etc...

# @(#) cleanup.pl - <DESCRIPTION> # # Author: # Dave Roberts # # Synopsis: # cleanup.pl # Script to remove files considered to be "temporary". These are defin +ed as either # 1) being located in a temporary directory # 2) having a name (extension) considered to be temporary # # Further there is a minimum age limit (3 days) so that temporary file +s currently in use are not # removed. # # Description: # Script to remove files considered to be "temporary". These are defin +ed as either # 1) being located in a temporary directory # 2) having a name (extension) considered to be temporary # # Options: # # variable @TempFileExtn is an array of temporary file extensions # variable @TempDirsis an array of temporary directory names # variable $minage is set to the minimum file age (excluded from delet +e) in days # # Exit Status: # # Caveats/Warnings: # # See Also: # # Files: # # Start comments/code here - will not be processed into manual pages # # Copyright © Dave Roberts 2010 # #********************************************************************* +********* use strict; use Carp; use File::Copy; use File::Find; use File::stat; use Win32::AdminMisc; use Net::SMTP; use Net::SMTP::SSL; use MIME::Base64; use File::HomeDir; use strict "vars"; use strict "refs"; use strict "subs"; use Time::HiRes qw(usleep gettimeofday tv_interval); my ($machine) = Win32::NodeName; # Determine Machine (Comp +uter) name my ($name) = Win32::LoginName; my ($bdy) = 'Daves Boundary'; my ($runtime) = time; my ($datetime) = &datetime($runtime); my ( $mailrelay, $sender ); my ( $ID, $MAJOR, $MINOR, $YEAR, $MONTH, $DAY, $TIME, $AUTHOR ) = q$Id: cleanup.pl 1.7 2010/09/12 15:29:48 Dave.Roberts Exp $ =~ /Id: (.+)\s+(\d+)\.(\d+)\s(\d+)\/(\d+)\/(\d+)\s(.+)\s(.+)\s(.+)\s(.? ++)/; my ($message) = <<"EOT"; ********************************************************************** +********* Executing script $ID Version $MAJOR.$MINOR Date $DAY-$MONTH-$YEAR Time $TIME Author $AUTHOR Execution: Computer $machine Account $name Date/Time $datetime ********************************************************************** +********* EOT print $message; my ($ts) = [gettimeofday]; my ($to) = 'dave.roberts@cummins.com'; my ($from) = $ENV{'COMPUTERNAME'}; $mailrelay = 'mysmtpserver.com'; $sender = 'me@myaddress.com'; END { &report( $mailrelay, $sender ); } my (%stats); # Identify local drives ---------------------------------------------- +--------------------------- my (%DriveType) = ( # &DRIVE_UNKNOWN => "Unknown", # &DRIVE_NO_ROOT_DIR => "No Root Dir", &DRIVE_REMOTE => "Remote", &DRIVE_REMOVABLE => "Removable", &DRIVE_FIXED => "Fixed", &DRIVE_CDROM => "CDROM", &DRIVE_RAMDISK => "Ramdisk", ); # Temporary Files --------------------------------------------------- +---------------------- my (@TempFileExtn) = qw( \.tmp$ \.swp$ \.pl~$ \.[0-9a-z]+~$ ); # Temporary Dirs ---------------------------------------------------- +---------------------- my (@TempDirs) = qw( \/tmp\/ \/temp\/ \/Tmp\/ \/Temp\/ ); # Minimum file age -------------------------------------------------- +---------------------- my ($minage) = 0; # age in days my (%Drives); my ($fs); foreach my $Drive ( Win32::AdminMisc::GetDrives() ) { my $Type = Win32::AdminMisc::GetDriveType($Drive); if ( DRIVE_REMOTE != $Type ) { $Drives{$Drive} = { size => 0, free => 0 }; if ( ( DRIVE_REMOVABLE == $Type ) || ( DRIVE_FIXED == $Type ) ) { if ( my %Volume = Win32::AdminMisc::GetVolumeInfo($Drive) +) { ( $Drives{$Drive}->{size}, $Drives{$Drive}->{free} ) = Win32::AdminMisc::GetDriveSpace($Drive); $Drives{$Drive}->{serial} = uc( sprintf( "%x", $Volume{Serial} ) ); $Drives{$Drive}->{serial} =~ s/(....)(....)/$1-$2/; $Drives{$Drive}->{fs} = $Volume{FileSystemName}; $Drives{$Drive}->{volume} = $Volume{Volume}; } } $Drives{$Drive}->{type} = $Type; if ( DRIVE_REMOVABLE != $Type && &DRIVE_CDROM != $Type ) { my %Volume = Win32::AdminMisc::GetVolumeInfo($Drive); $Drives{$Drive}->{filesystem} = $Volume{FileSystemName}; } } } foreach my $d ( sort keys %Drives ) { message( "--------------------------------------------------------------------- +--------------------" ); $fs = $d; $fs =~ s/\\$/\//; message("Drive $fs "); foreach my $k ( sort keys %{ %Drives->{$d} } ) { if ( $k eq "type" ) { message( sprintf " %15s: %s", $k, $DriveType{ %Drives->{$d}->{$k} } ); } elsif ( ( $k eq "free" ) | ( $k eq "size" ) ) { message( sprintf " %15s: %s", $k, commify( %Drives->{$d}->{$k} ) ); } else { message( sprintf " %15s: %s", $k, %Drives->{$d}->{$k} ) +; } } message(" "); foreach my $k ( sort keys %{ %Drives->{$d} } ) { if ( $k eq "type" ) { message( sprintf " %15s: %s", $k, $DriveType{ %Drives->{$d}->{$k} } ); if ( $DriveType{ %Drives->{$d}->{$k} } eq "Fixed" ) { $Drives{$fs}->{no_deleted} = 0; $Drives{$fs}->{size_deleted} = 0; $Drives{$fs}->{no_undeleted} = 0; $Drives{$fs}->{size_undeleted} = 0; $Drives{$fs}->{no_dir_deleted} = 0; $Drives{$fs}->{no_dir_undeleted} = 0; &cleanup(); } } } } sub cleanup { message("\tchecking $fs for temporary and invalid files"); find( \&wanted, $fs ); message( sprintf " Deleted %s files (%s bytes)", $Drives{$fs}->{no_deleted}, commify( $Drives{$fs}->{size_deleted} ) ); message( sprintf " Unable to delete %s files (%s bytes)", $Drives{$fs}->{no_undeleted}, commify( $Drives{$fs}->{size_undeleted} ) ); message( sprintf " Deleted %s directories (unable to delete %s Direct +ories)", $Drives{$fs}->{no_dir_deleted}, $Drives{$fs}->{no_dir_undeleted} ); } sub wanted { my ($size); foreach my $extn (@TempFileExtn) { if ( $File::Find::name =~ m/$extn/ ) { my ( $dev, $ino, $mode, $nlink, $uid, $gid ) = lstat($File::Find::name); if ( int( -M _ ) > $minage ) { $size = &delfile($File::Find::name); if ( $size > 0 ) { $Drives{$fs}->{size_deleted} += $size; $Drives{$fs}->{no_deleted} += 1; } elsif ( $size < 0 ) { $Drives{$fs}->{size_undeleted} += -$size; $Drives{$fs}->{no_undeleted} += 1; } elsif ( $size eq "D" ) { $Drives{$fs}->{no_dir_deleted} += 1; } elsif ( $size eq "-D" ) { $Drives{$fs}->{no_dir_undeleted} += 1; } else { #delfile returned zero size } } else { message( sprintf "\t\tskipping %s which is %s days old +", $File::Find::name, int( -M _ ) ); } } } foreach my $dir (@TempDirs) { if ( $File::Find::name =~ m/$dir/ ) { if ( int( -M _ ) > $minage ) { $size = &delfile($File::Find::name); if ( $size > 0 ) { $Drives{$fs}->{size_deleted} += $size; $Drives{$fs}->{no_deleted} += 1; } elsif ( $size < 0 ) { $Drives{$fs}->{size_undeleted} += -$size; $Drives{$fs}->{no_undeleted} += 1; } elsif ( $size eq "D" ) { $Drives{$fs}->{no_dir_deleted} += 1; } elsif ( $size eq "-D" ) { $Drives{$fs}->{no_dir_undeleted} += 1; } else { # delfile returned zero size } } else { message( sprintf "\t\tskipping file %s which is %s day +s old", $File::Find::name, int( -M _ ) ); } } } } sub delfile { my ($file) = @_; if ( -f $file ) { my ($sb) = stat($file); if ( unlink $file ) { message( sprintf "\t\tdeleted %s (%s bytes)", $file, $sb-> +size ); return $sb->size; } else { message( sprintf "\t\tunable to delete %s (%s bytes)", $file, $sb->size ); return -$sb->size; } } elsif ( -d $file ) { if ( rmdir($file) ) { message("\t\tremoved directory $file"); return "D"; } else { message("\t\tunable to remove directory $file"); return "-D"; } } else { message("\t\t! $file is neither a file or a directory"); } } sub datetime { my ( $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst ) + = localtime(time); my ($month) = ( 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' )[$mon]; my ($datetime) = sprintf "%2d/%s/%02d %2d:%02d:%02d", $mday, $month, ( $year + 1900 ), $hour, $min, $sec; return $datetime; } sub commify { my $text = reverse $_[0]; $text =~ s/(\d\d\d)(?=\d)(?!\d*\.)/$1,/g; return scalar reverse $text; } sub report { my ( $mailrelay, $from, $password ) = @_; #----------------------------------------------------------------- +---------- # report activity for this script execution #----------------------------------------------------------------- +---------- # Compile message my ($subject) = "Script log for $ID executed at " . $datetime . " from machine " . $machine; my ($smtp); if ( $mailrelay eq "smtp.gmail.com" ) { if ( not $smtp = Net::SMTP::SSL->new( $mailrelay, Port => 465, Debug => 0 ) ) { die "Could not connect to mail server\n"; } $smtp->auth( $from, $password ) || die "SMTP authentication failed for $mailrelay!\n"; } else { $smtp = Net::SMTP->new( $mailrelay, Debug => 0 ) || print "failed to connect to $mailrelay ($!)\n"; } if ( !$smtp ) { message("$mailrelay (no connection)"); print "unable to send mail to $mailrelay\n"; print "this is the mail body that would have been sent\n\n"; print "Script File: $ID executed at " . $datetime . "\n"; foreach ( split( /\n/, $message ) ) { print "\t$_\n"; } } else { $smtp->mail($from); $smtp->to($to); $smtp->data(); $smtp->datasend("To: $to\n"); $smtp->datasend("Subject: $subject\n"); $smtp->datasend("MIME-Version: 1.0\n"); $smtp->datasend("Content-Type: multipart/mixed; BOUNDARY=\"$bd +y\"\n"); $smtp->datasend("\n"); $smtp->datasend("--$bdy\n"); $smtp->datasend( "Script File: $ID executed at " . $datetime . + "\n" ); $smtp->datasend("\n"); foreach ( split( /\n/, $message ) ) { $smtp->datasend($_); $smtp->datasend("\n"); } $smtp->datasend("\n"); $smtp->datasend("--$bdy--\n"); $smtp->datasend("This is the epilogue - it should be ignored\n +"); $smtp->datasend("\n"); $smtp->dataend(); $smtp->quit || print "smtp quit failed\n"; } } sub message { my ($entry) = @_; print $entry . "\n"; $message = $message . $entry . "\n"; }