Reputation: 3
I am trying to move files from one folder(source
) that are NOT in another folder (stock files
) and where source files are older than 30 days to a backup location
I have tried several times but I can't seem to get it right.
$days = 30
$Source = "G:\fs01\"
$Destination = "G:\fso2\"
$StockFileLocation = "g:\fso1Stock\"
$FileExtention = ".mpr"
$limit = (Get-Date).AddDays(-$days)
$SourceFiles = (Get-ChildItem $Source | where {$_.extension -eq $FileExtention} | % {$_.Name})
$StockFiles = (Get-ChildItem $StockFileLocation | where {$_.extension -eq $FileExtention} | % {$_.Name})
Goal: for each file in source.
If file name in source < > file name in Stock File Location and
source is older than 30 days then move file to destination.
Upvotes: 0
Views: 72
Reputation: 61068
I think this should do it:
$days = 30
$Source = "G:\fs01\"
$Destination = "G:\fso2\"
$StockFileLocation = "g:\fso1Stock\"
$limit = (Get-Date).AddDays(-$days)
# get an array of filenames already in the $StockFileLocation folder (names only)
$StockFiles = Get-ChildItem -Path $StockFileLocation -Filter '*.mpr' -File | Select-Object -ExpandProperty Name
# get an array of FileInfo objects of .mpr files older that $limit and loop through
$SourceFiles = Get-ChildItem -Path $Source -Filter '*.mpr' -File | Where-Object { $_.LastWriteTime -lt $limit }
$SourceFiles | ForEach-Object {
if ($StockFiles -notcontains $_.Name) {
$_ | Move-Item -Destination $Destination -WhatIf
}
}
Remove the -WhatIf
switch when you are satisfied with the results
As requested in your comment, below the same thing wrapped in a function:
function Move-OldNotInStock {
[CmdletBinding()]
param(
[Parameter(Mandatory = $true, Position = 0)]
[Alias('Path')]
[string[]]$Source, # Specifies a path to one or more source locations. Wildcards are accepted.
[Parameter(Mandatory = $true, Position = 1)] # The destination folder. Will be created if it does not exist
[string]$Destination,
[string]$StockFileLocation = "G:\fso1Stock" , # The folder for the files 'in stock'. defaults to "G:\fso1Stock"
[int]$AgeInDays = 30, # The number of days to consider files old. Defaults to 30
[string]$FilePattern = '*.mpr', # The file pattern of files to collect. Defaults to '*.mpr'
[switch]$Recurse, # Whether or not subfolders in the source path(s) should be included
[switch]$WhatIf # 'Chicken switch'. Allows to run the function without actually moving files.
)
# create the destination path if it does not exist
if (!(Test-Path -Path $Destination -PathType Container)) {
Write-Verbose "Creating folder '$Destination'"
New-Item -Path $Destination -ItemType 'Directory' -Force | Out-Null
}
$limit = (Get-Date).AddDays(-$AgeInDays)
# get an array of filenames already in the $StockFileLocation folder (names only)
$StockFiles = Get-ChildItem -Path $StockFileLocation -Filter $FilePattern -File | Select-Object -ExpandProperty Name
# get an array of FileInfo objects of .mpr files older that $limit and loop through
Get-ChildItem -Path $Source -Filter $FilePattern -File -Recurse:$Recurse |
Where-Object { $_.LastWriteTime -lt $limit -and $StockFiles -notcontains $_.Name } |
Move-Item -Destination $Destination -WhatIf:$WhatIf
}
Use like this to accept the default values for -StockFileLocation
, -AgeInDays
, -FilePattern
Move-OldNotInStock -Source "G:\fs01" -Destination "G:\fso2" -WhatIf
I have shortened the code to get the files, filter them on age and (non) existance in the stockfolder and removing them a bit. Perhaps this makes the code a little less readable..?
Upvotes: 1
Reputation:
If I understood your requirements right, you can do it in a single pipeline
$days = 30
$Source = "G:\fs01\"
$Destination = "G:\fso2\"
$StockFileLocation = "g:\fso1Stock\"
$FileExtention = "*.mpr"
$limit = (Get-Date).Date.AddDays(-$days)
Get-ChildItem -Path $Source -Filter $FileExtention |
Where-Object {$_.LastWriteTime -lt $Limit -and
(!(Test-Path ($_.FullName -replace [Regex]::Escape($Source),$StockFileLocation)))}|
Move-Item $Destination -WhatIf
If output looks OK, remove the trailing -WhatIf
Upvotes: 2