Handy PowerShell script to crawl file shares and collect information on their structure

 

Hi Community,

I’ve been a bit busy lately (work and family related with the arrival of my second children) but it’s always great to share information with you. A couple of weeks ago, I was working on this engagement to decide whether to move to the cloud or not (It wasn’t a brainer for me taking into consideration the existing technology stack my customer has, but more importantly I needed to collect evidence or facts in order to help them make a decision).

My customer has quite some file shares spread across Windows and multiple NAS. I had to write a PowerShell script (see below) for this task. Personally, I don’t like any scripting language mainly because I expect my code to be compiled, linked besides being able to tweak my code to perform as I want it too, but like I said it’s my personal opinion.

I hope you’ll find it useful.

param([String]$targetServer=“Win2012R2”)

CLS

$shareCount = 0
$startAnalysis = (Get-Date)
$loggedOnUser = Get-WMIObject -class Win32_ComputerSystem | select username

Write-Host “**************************************************************************”
Write-Host “**        File Share Report – Shares on: $targetServer              “
Write-Host “**        Currently logged on as: $loggedOnUser                     ”
Write-Host “**        Analysis start: $startAnalysis”
Write-Host “**************************************************************************”

If (-Not [string]::IsNullOrEmpty($targetServer)) {
 
$existingShares = Get-WmiObject -class Win32_Share -computername $targetServer `
    
-filter “Type=0 And Name Like ‘%[^$]’ And Name <> ‘NETLOGON’ And Name <> ‘SYSVOL'”
    
    
foreach($share in $existingShares) {
       
$results = $null
       
$uncPath = “\\$targetServer\\”+$share.Name
       
       
# Let‘s display information on fileshares on target server (Summary)
        $stats = dir $uncPath -recurse -errorAction “SilentlyContinue” | `
            where {-Not $_.PSIsContainer}| Measure-Object -Property length -Sum
        $results = New-Object -TypeName PSObject -Property @{
                        Computername=$targetServer
                        LocalPath=$share.Path
                        UNCPath=$uncPath
                        SizeKB=[math]::Round(($stats.sum/1KB),2)
                        NumberFiles=$stats.count
            }
       
         $results | Format-Table ComputerName, LocalPath, UNCPath, SizeKB, NumberFiles
        
         # Let’
s display a breakdown on file types and their sizes
        
Get-ChildItem -Path $uncPath -Recurse |
           
Where-Object { !$_.PSIsContainer } |
               
Group-Object Extension |

         Select-Object @{n=“Extension”;e={$_.Name -replace ‘^\.’}}, `
                       
@{n=“Size(MB)”;e={[math]::Round((($_.Group | Measure-Object Length -Sum).Sum / 1MB), 2)}}, 
                      
@{n=“Average Size(MB)”;e={[math]::Round((($_.Group | Measure-Object Length -Average).Average / 1MB), 2)}},
                      
@{n=“Maximum Size (MB)”;e={[math]::Round((($_.Group | Measure-Object Length -Maximum).Maximum / 1MB), 2)}},  #, 
                      
Count | Format-Table
        
        
        
# Let‘s display a breakdown on files in shares by age bucket
         $files=dir $uncPath -recurse |
         Select Fullname, CreationTime, LastWriteTime, Length,
            @{Name=”Age”;Expression={(Get-Date)-$_.LastWriteTime}},
            @{Name=”Days”;Expression={[int]((Get-Date)-$_.LastWriteTime).TotalDays}}
       
         $summary=@{
                Path=$uncPath
                OverAYear = ($files | Where {$_.Days -gt 365} | Measure-Object).Count
                ‘
_365Days‘ = ($files | Where {$_.Days -gt 180 -AND $_.Days -le 365} | Measure-Object).Count
                ‘
_180Days‘ = ($files | Where {$_.Days -gt 90 -AND $_.Days -le 180} | Measure-Object).Count
                ‘
_90Days‘ =  ($files | Where {$_.Days -gt 30 -AND $_.Days -le 90} | Measure-Object).Count
                ‘
_30Days‘ =  ($files | Where {$_.Days -gt 7 -AND $_.Days -le 30} | Measure-Object).Count
                ‘
_7Days‘ =   ($files | Where {$_.Days -gt 0 -AND $_.Days -le 7} | Measure-Object).Count
         }
       
        $ageBucket =  New-Object -TypeName PSObject -Property $summary | Select Path, OverAYear, _365Days, _180Days, _90Days, _30Days, _7Days
       
        [Console]::Write(“`n`r*****************************`nFiles grouped by age (Count)`n*****************************`n`rPath: {0}`nOver a year: {1}`n365 days: {2}`n”, $ageBucket.Path, $ageBucket.OverAYear,  $ageBucket._365Days)
        [Console]::Write(“180 days: {0}`n90 days: {1}`n30 days: {2}`n”, $ageBucket._180Days, $ageBucket._90Days,  $ageBucket._30Days)
        [Console]::Write(“7 days: {0}`n”, $ageBucket._7Days)
       
        $shareCount += 1
       
        Write-Host “——————————————————————————“
     }
    
     $endAnalysis = (Get-Date) – $startAnalysis
     Write-Host “Total Shares: $shareCount”
     Write-Host “Analysis Execution Time: $endAnalysis”
} Else {
   Write-Host “**  targetServer needs to be specified.    **” -ForegroundColor Red

}

 

Leave a Reply

Your email address will not be published. Required fields are marked *