0

I'm writing a script to archive files in folders, which works fine. But now I want to implement an extra filter called $OlderThan and that's where I'm struggling now.

The script:

[CmdletBinding(SupportsShouldProcess=$True)]
Param (
    [parameter(Mandatory=$true,Position=0)]
    [ValidateNotNullOrEmpty()]
    [ValidateScript({Test-Path $_ -PathType Container})]
    [String]$Source,
    [parameter(Mandatory=$false,Position=1)]
    [ValidateNotNullOrEmpty()]
    [ValidateScript({Test-Path $_ -PathType Container})]
    [String]$Destination = $Source,
    [parameter(Mandatory=$false)]
    [ValidateSet('Year','Year\Month','Year-Month')]
    [String]$Structure = 'Year\Month',
    [parameter(Mandatory=$false)]
    [ValidateSet('Day','Month','Year')]
    [String]$OlderThan = 'Day',
    [parameter(Mandatory=$false)]
    [Int]$Quantity = '1'
)
Begin {
    $Today = Get-Date
    $When = ($Today.AddDays(-"$Quantity")).Date
}
Process {
    Get-ChildItem $Source -File | ForEach-Object {
        $File = $_
        # Get folder name
        $ChildPath = Switch ($Structure) {
            'Year'       { [String]$File.CreationTime.Year }
            'Year\Month' { [String]$File.CreationTime.Year+"\"+$File.CreationTime.ToString("MM") }
            'Year-Month' { [String]$File.CreationTime.Year+"-"+$File.CreationTime.ToString("MM") }
        }
        $Target = Join-Path -Path $Destination -ChildPath $ChildPath

        # Move the file
        if (Test-Path $Target -PathType Container) { 
            Move-Item -Path $File.FullName -Destination $Target -ErrorAction SilentlyContinue
        } 
        else {
            New-Item $Target -Type Directory | Out-Null
            Move-Item -Path $File.FullName -Destination $Target -ErrorAction SilentlyContinue
        }
    }
}

The extra filter:

Switch ($OlderThan) {
    'Day'    { where ($File.CreationTime -le $(($Today.AddDays(-"$Quantity")).Date))}
    'Month'  { where {$File.CreationTime.Month -lt $Today.Month }}
    'Year'   { where {$File.CreationTime.Year -lt $Today.Year }}
}

How can I implement this the best way? The purpose is that when Day, Month or Year is chosen, this filter is applied after Get-ChildItem based on the file's CreationTime. So only those files are moved that comply with the filter.

For the moment I created a workaround for this, by creating a function like below. But is it really needed to create a function just to have these 3 filters between the pipeline? It feels like I'm over complicating things.

Current workaround:

Function Select-Stuff {
    Param(
        [Parameter(ValueFromPipeline=$True)]
        $File
    )
    Process {
        Switch ($OlderThan) {
            'Day'    { if ($File.CreationTime -le $When) {Write-Output $File} }
            'Month'  { if ($File.CreationTime.Month -lt $Today.Month) {Write-Output $File} }
            'Year'   { if ($File.CreationTime.Year -lt $Today.Year) {Write-Output $File} }
        }
    }
}

Get-ChildItem $Source -File | Select-Stuff | ForEach-Object {

Thank you for your help.

1
  • I can off course always make a script block out of it and call it from within the Switch. But I would like to be able to use the pipeline if possible. Commented Sep 16, 2014 at 11:15

1 Answer 1

1

I think the easiest way to create that filter would be to (literally) create that filter:

 Begin {
    $Today = Get-Date
    $When = ($Today.AddDays(-"$Quantity")).Date

    Switch ($OlderThan) {
    'Day'    { filter Get-OlderThan  { if ($_.CreationTime -le $(($Today.AddDays(-"$Quantity").Date))) {$_} } }
    'Month'  { filter Get-OlderThan { if ( $_.CreationTime.Month -lt $Today.Month) {$_} } }
    'Year'   { filter Get-OlderThan { if ($_.CreationTime.Year -lt $Today.Year) {$_} } }
    Default  { filter Get-OlderThan {$_ } }
  }
}
Process {
    Get-ChildItem $Source -File | 
    Get-OlderThan | ForEach-Object {
    ...
    }
Sign up to request clarification or add additional context in comments.

3 Comments

Awesome, awesome, awesome! I didn't know about the existence of Filter in PowerShell. And writing a function specifically for this with parameters and everything seemed like overkill. Thank you very much mjolinor, appreciate it!
Welcome! Filters are basically just a function that implicitly have only a Process block. You don't see them used much, but they can be handy things on occasion :)
I fully agree! They make things a lot cleaner/easier to read when it's only about filtering stuff :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.