简体   繁体   中英

Move Files Based on Date Stamp in File Name

I'm new to PowerShell unfortunately, and I have a number of files that I would to like to archive with PowerShell on a monthly basis. Each file has a YYYYMM date stamp in the file name. I'd like to move files that have a date stamp older than 24 months.

Example:

file1_201903.txt  
file2_201902.txt  
...  
file3_201703.txt (this should be archived)  
file4_201702.txt (this should be archived)

Note that the source files reside in a directory with a number of subfolders. I'd like the script to check all subfolders. The folders do not need to be replicated in the destination.

Here's what I've tried so far:

$SourceDir = 'C:\source'
$DestDir   = 'C:\destination'
$YearsAgo  = 2

$Then = (Get-Date).AddYears(-$YearsAgo).Date

Get-ChildItem -Path $SourceDir |
    Where-Object {
        $DatePart = ($_.BaseName -split '_')[1]

        $FileDate = [DateTime]::ParseExact($DatePart, 'yyyyMMdd', [CultureInfo]::CurrentCulture)

        $FileDate -lt $Then
    } |
    Move-Item -Destination $DestDir

The date parts in the filenames do not have a value for the Day. The format should therefore be yyyyMM , not yyyyMMdd .

Since the format is a sortable string, you do not have to convert to a DateTime object and can go ahead and compare the strings:

$SourceDir = 'C:\source'
$DestDir   = 'C:\destination'
$YearsAgo  = -2
$Then      = '{0:yyyyMM}' -f (Get-Date).AddYears($YearsAgo)  # returns a String "201703"

Get-ChildItem -Path $SourceDir | ForEach-Object {
    $DatePart = ( $_.BaseName -split '_' )[1]
    # comparing sortable date strings
    if ($DatePart -lt $Then) {
        $_ | Move-Item -Destination $DestDir
    } 
}

If you do want to compare on DateTime objects, this should do it:

$SourceDir = 'C:\source'
$DestDir   = 'C:\destination'
$YearsAgo  = -2

$RefDate   = ('{0:yyyyMM}' -f (Get-Date).AddYears($YearsAgo))  # returns a String "201703"
# convert this string into a DateTime object
$Then      = [DateTime]::ParseExact( $RefDate, 'yyyyMM', [cultureinfo]::CurrentCulture )

Get-ChildItem -Path $SourceDir | ForEach-Object {
    $DatePart = ( $_.BaseName -split '_' )[1]
    $FileDate = [DateTime]::ParseExact( $DatePart, 'yyyyMM', [cultureinfo]::CurrentCulture )
    # comparing DateTime objects
    if ($FileDate -lt $Then) {
        $_ | Move-Item -Destination $DestDir
    } 
}

That doesn't look that bad actually. ;-) But your -FilterScript block in your Where-Object needs a little tweak:

$SourceDir = 'C:\source'
$DestDir   = 'C:\destination'
$YearsAgo  = -2
$Then = ( Get-Date ).AddYears( $YearsAgo ).Date

Get-ChildItem -Path $SourceDir -Recurse |
    Where-Object {
        [datetime]::ParseExact( $(( $_.BaseName -split '_' )[1]), 'yyyyMMdd', [cultureinfo]::CurrentCulture ) -lt $Then
    } |
        Move-Item -Destination $DestDir

You could use a little more descriptive way with a Foreach-Object . Sometimes that's easier to read/understand/follow:

Get-ChildItem -Path $SourceDir -Recurse |
    ForEach-Object{
        $DatePart = ( $_.BaseName -split '_' )[1]
        $FileDate = [datetime]::ParseExact( $DatePart, 'yyyyMMdd', [cultureinfo]::CurrentCulture )
        if ($FileDate -lt $Then) {
            Move-Item -Path $_.FullName -Destination $DestDir
        } 
    }

Unfortunately I cannot test at the moment. So try and let me know please. ;-)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM