Your basic ITPro blog... What's going on at work, what I'm interested in.

Monday, June 30, 2008

File Management in PowerShell

Biggest files? Oldest files? Duplicates?

I am guessing that, at one time or another, most of us have asked these questions of our file stores. Answers to these questions help us make informed decisions regarding storage management, archiving, etc. I know there are 3rd party apps out there that do this sort of thing. We have Storage Exec installed on an older server. It have a lot of functionality (much of which we don't use). Mainly, we use it to ask these simple questions. I thought, why pay money for something when you don't have to? Why install another app on your file server?

To that end, I am currently working on three PoSH scripts (functions) that will answer these questions. I pre-load these scripts in my PowerShell profile so that these functions are available just like cmdlets. It keeps them handy.

The first one I want to share is: Get-BigFiles

This function is pretty straightforward and simple. You can pass it a path, quantity in results, and minimum file size. It has some simple formatting to make the output (currently to console) a bit easier to read. It also reports back the time it took to run. I consider this version 0.10

Some things that are in my head include:

  • Would using custom objects or arrays to store results make things easier to manage/report on/output/etc.? Other techniques?
  • Want to be able to output to a file (HTML or TXT, for example).
  • As I have stated before, I still think primarily in terms of VB. How would this script benefit from a more PowerShell-native approach?
  • What other features would this script benefit from?

As of now, this script functions. It gives me the information I am asking of it. In that, it is successful. It may not be the most elegant, most 'correct' way of doing things. But, if you get the answer you need and are then able to move forward doing your job, then you have a tool of worth. I welcome comments and suggestions.

###################################################################
# Function: Get-BigFiles
# 
# Description: Generates a list of files meeting the PATH,
#              QUANTITY, and SIZE criteria
#
# Input: $Path as string        ( example: "C:\windows" )
#        $howMany as integer    ( example: 20 )
#         $minSize as Integer64    ( example: 100MB )
#
# Usage:     Get-BigFiles "C:\scripts" 5 10MB
#            Get-BigFiles -howMany 20
#
# Recursively returns the largest files meeting criteria
###################################################################
function Get-BigFiles
(    [string]$Path = (Get-Location),
    [int]$howMany = 10,
    [long]$minSize = 1GB
)
{
    if (Test-Path $Path) {
        Write-Host "`n`nChecking for the $howMany largest file(s) under the `'$Path`' folder."
        if ($minSize -lt 1KB) {
            Write-Host "Minimum file size in report: NONE"
        }
        elseif ($minSize -lt 1MB) {
            Write-Host "Minimum file size in report: "($minSize / 1KB) "KB"
        }
        elseif ($minSize -lt 1GB) {
            Write-Host "Minimum file size in report: "($minSize / 1MB) "MB"
        }
        else {
            Write-Host "Minimum file size in report: "($minSize / 1GB) "GB"
        }
        $startTime = Get-Date
        Write-Host "  Start: $startTime"
        Write-Host "Depending on folder size, this could take a while..."
        $results = (Get-ChildItem $Path -Recurse |
                    where {$_.PSIsContainer -eq $FALSE -and $_.Length -ge $minSize} |
                    Sort-Object Length -Descending |
                    Select-Object     Directory,
                                    Name,
                                    Length,
                                    LastAccessTime -First $howMany
                    )
        if ($results) {
            foreach ($file in $results) {
                if ($file.Length -lt 1KB) {
                    $formattedLength = $file.Length.toString() + " Bytes"
                }
                elseif ($file.Length -lt 1MB) {
                    $formattedLength = [string]::Format("{0:#.##}",($file.Length / 1KB)) + " KB"
                }
                elseif ($file.Length -lt 1GB) {
                    $formattedLength = [string]::Format("{0:#.##}",($file.Length / 1MB)) + " MB"
                }
                else {
                    $formattedLength = [string]::Format("{0:#.##}",($file.Length / 1GB)) + " GB"
                }
                
                Write-Host "`nDirectory:   " $file.Directory
                Write-Host "Name:        " $file.Name
                Write-Host "Length:      " $formattedLength
                Write-Host "Last Access: " $file.LastAccessTime
            }
        }
        else {
            Write-Host "No files meet the minimum criteria."
        }
    }
    else {
        Write-Host "`'$Path`' is an invalid path."
    }
    $endTime = Get-Date
    Write-Host "`n  End: $endTime"
    Write-Host "`nDuration: " ($endTime - $startTime).Duration()
}

No comments:

Additional Info

My photo
email: support (AT) mangrumtech (DOT) com
mobile: 480-270-4332