Moving files into a file structure on a monthly basis - powershell

Hi I am trying to move files every month into a file structure, the structure is like so:
Year >> Quarter >> Month >> FileType
The log files are automatically placed into a log folder - I want to m,ove any of these files into this structure above.
I tried the following:
function moveFiles{
# The three parameters.
param([string]$sourceDir, [string]$type, [string]$destinationDir)
# Move the files
Get-ChildItem -Path $sourceDir -Include $type | Move-Item -Destination $destinationDir - Force
}
However each month it is moving every file into the new month, I know this is to do with the recurse but I removed it and no files were moved.
Any help would be appreciated.
How I am calling the function:
$sourceDir = "C:\Logs"
$destinationExcelDir = ($monthFolder + "\Excel Files");
#Moving all Excel files from logs folder to Archive
moveFiles $sourceDir "*.xls" $destinationExcelDir
Using write-host I can confirm both paths are correct and also different however I am trying to copy the files into subfolders in the same main directory.
E.g. $destinationExcelDir is "C:\Logs\2014\quarter 4\November\Excel"

Assuming you want to sort the files in C:\logs by their last write time, the following function revision should help. You would only have to supply the path with a wild card containing the extension and the last folder name in the path name as arguments to the function.
Example Usage: moveFiles C:\Logs*.xls "Excel Files"
function moveFiles {
param(
[string]$source,
[string]$destinationDir
)
Get-ChildItem $source -file | foreach {
$year = $_.LastWriteTime.Year
# Switch statement to get the quarter name
switch -regex ($_.LastWriteTime.Month) {
"[1-3]" {$quarter = 'Quarter 1'}
"[4-6]" {$quarter = 'Quarter 2'}
"[7-9]" {$quarter = 'Quarter 3'}
"[10-12]" {$quarter = 'Quarter 4'}
}
# Switch statement to get the month name
switch ($_.LastWriteTime.Month) {
'1' {$month = 'January'}
'2' {$month = 'Feburary'}
'3' {$month = 'March'}
'4' {$month = 'April'}
'5' {$month = 'May'}
'6' {$month = 'June'}
'7' {$month = 'July'}
'8' {$month = 'August'}
'9' {$month = 'September'}
'10' {$month = 'October'}
'11' {$month = 'November'}
'12' {$month = 'December'}
}
# Create the destination folder if it doesn't exist
if (!(test-path "C:\Logs\$year\$quarter\$month\$destinationDir")) {
New-Item -ItemType Directory -Path "C:\Logs\$year\$quarter\$month\$destinationDir"
}
# Move the files into the correct folder
move-item $_ "C:\Logs\$year\$quarter\$month\$destinationDir"
}
}

Here is a function that has some parameters set to mandatory so it should prompt you for input if you don't provide it when you run it. Destination directory is set to pre-defined locations based on file type, but can be over-ridden if specified at run time. Month input is assumed to be a number. If this were to go into a production environment, I'd expect some input validations, confirmation prompts, and possibly result validations. Making this a wiki answer to see if anyone wants to add anything.
Usage:
Move-Files -sourceDir c:\temp -type xls -year 2014 -month 11
Over-ride:
Move-Files -sourceDir c:\temp -type xls -year 2014 -month 11 -destinationDir "Override Location"
Function Move-Files{
param(
[Parameter(Mandatory=$True)][string]$sourceDir,
[Parameter(Mandatory=$True)][string]$type,
[string]$destinationDir,
[Parameter(Mandatory=$True)][string]$year,
[Parameter(Mandatory=$True)][string]$month
)
# Add wildcard and period to search for all files of the given type by extension
[string]$searchtype = '*.' + $type
# Determine quarter of the year
if ($month -like "1" -or $month -like "2" -or $month -like "3"){[string]$quarter = "Quarter 1"}
elseif ($month -like "4" -or $month -like "5" -or $month -like "6"){[string]$quarter = "Quarter 2"}
elseif ($month -like "7" -or $month -like "8" -or $month -like "9"){[string]$quarter = "Quarter 3"}
elseif ($month -like "10" -or $month -like "11" -or $month -like "12"){[string]$quarter = "Quarter 4"}
# Read month number to pull month name
[string]$monthname = (get-date -Month $month).tostring("MMMM")
# Set destination based on file type.
if($type -like "xls" -and $destinationDir -like $null){[string]$destinationDir = "Excel Files"}
elseif($type -like "jpg" -and $destinationDir -like $null){[string]$destinationDir = "Image Files"}
elseif ($destinationDir -like $null){[string]$destinationDir = Read-Host 'Please enter destination directory.'}
# Build complete destination path
[string]$completeDir = $sourceDir + '\' + $year + '\' + $quarter + '\' + $monthname + '\' + $destinationDir
# Check for directory and create if not found
if (!(test-path $completeDir)) {[void](New-Item -ItemType Directory -Path $completeDir)}
# Move the files
Get-ChildItem -Path $($sourceDir + "\" + $searchtype) | Move-Item -Destination $completeDir -Force
}

Related

Unable to delete or rename directories or Files with Multiple Square ([[...]] brackets in Path [duplicate]

This question already has answers here:
How can I make PowerShell handle [ or ] in file name well?
(2 answers)
Error "Could not find a part of the path" while setting attributes on an existing file
(2 answers)
Closed 4 months ago.
This post was edited and submitted for review 4 months ago and failed to reopen the post:
Original close reason(s) were not resolved
I have regular Jobs to clean up old User Windows-Profile directories on a central NAS.
Last time I had Directories containing double square Brackets in the path (Import from Macromedia or so). This looks like:
\server.ad.local\HOME1\Username\System\Anwendungsdaten\Macromedia\FlashPlayer\SharedObjects\G5EUZBX2\www.daserste.de\[[IMPORT]]\players.edgesuite.net\flash\plugins\osmf\advanced-streaming-plugin\v3.4\osmf2.0\AkamaiAdvancedStreamingPlugin.swf\HDCore.sol
As this Job should run automatically with Powershell I tired various things:
Tried to replace the brackets an rename the folder - no success
Tried LiteralPath for Remove-Item - no success
Tried to Deleted with Scripting.FileSystemObject - no success
I always get the following error Message:
The Element ... cannot be removed: A part of the Path "HDCore.sol" cannot be found.
Are there any ideas?
Tried to rename the Folder, tried remove-item with -LiteralPath, tried to use FileSystemObject.
All of the actions gave the same result: Error
Just to complete: here are the functions I used last:
Function RemoveChar
{
Param ($Path)
$Pattern = '#|&|%|\[{1,}|\]{1,}|\^|\s|\.{2,}'
if ($Path -imatch $Pattern){
Rename-Item -Path $Path -NewName ($Path -replace $Pattern,'') -ErrorAction SilentlyContinue
return ($Path -replace $Pattern,'')
} else {
return $Path
}
}
Function Truncate
{
Param ($Path)
$total_path_length_threshold = 248 # maximal erlaubte Zeichenzahl (248 für Verzeichnisse, 260 für Dateien)
$characters_to_truncate = 60 # Anzahl der zeichen, um die der name zu kürzen ist. Ein eindeutiger Index wird angehangen
$virtual_drive = "v:" # Für temp. Prozessing muss das Format "v:" haben
$collection = cmd /c dir $Path /s /b |? {$_.length -gt $total_path_length_threshold }
$count_paths = ($collection | measure).count - 1
foreach ($pathlong in $collection) {
$parent_path = Split-path -path $pathlong
subst $virtual_drive $parent_path
$leaf = split-path -leaf $pathlong
$short_virtual_path = join-path $virtual_drive $leaf
$item = Get-Item -LiteralPath $short_virtual_path
if (Test-Path -LiteralPath $item) {
$filename = $item.name
$filename_extension = $item.Extension
$basename = $item.BaseName
$basename_length = $basename.length
$new_index = "X" + $counter + "X"
$adjusted_characters_to_truncate = $characters_to_truncate + $new_index.length
if ( $basename_length -gt $adjusted_characters_to_truncate ) {
$length_to_use = $basename_length - $adjusted_characters_to_truncate
$new_filename = $basename.substring(0, $length_to_use ) + $new_index + $filename_extension
$new_path = $parent_path + $new_filename
$Path = $new_path
Rename-Item -LiteralPath $short_virtual_path -NewName $new_filename
}
}
subst v: /d
}
return $Path
}
Function removeRecursive
{
param([String] $Path)
$fso = new-object -com "Scripting.FileSystemObject"
function proc {
param($folder)
$folder.Files | foreach-object {
RemoveChar $_
}
$folder.Files | foreach-object {
$short = $fso.GetFile($_.FullName).ShortPath
LogWrite "$FullDate : Processing: $short"
$fso.DeleteFile($short,$true)
}
$folder.SubFolders | foreach-object {
proc $_
}
}
proc $fso.GetFolder($Path)
}
The function I call from main code is removeRecursive. And yes I tried Remove-Item -LiteralPath SomePath -Recursive -Force too but no success as well.

Powershell - Make a menu out of text file

In my adventure trying to learn Powershell, I am working on an extension on a script I have made. The idea is to make script there by adding ".iso" files into a folder. It will use that content in a menu so that I later can use it to select an iso file for a WM in Hyper-V
This is my version of how it will get the content in the first place
Get-ChildItem -Path C:\iso/*.iso -Name > C:\iso/nummer-temp.txt
Add-Content -Path C:\iso/nummer.txt ""
Get-Content -Path C:\iso/nummer-temp.txt | Add-Content -Path C:\iso/nummer.txt
When this code is run it will send an output like what i want. But my question is how do I use this output in a menu?
This is the best practice way to do so in powershell :
#lets say your .txt files gets this list after running get-content
$my_isos = $('win7.iso','win8.iso','win10.iso')
$user_choice = $my_isos | Out-GridView -Title 'Select the ISO File you want' -PassThru
#waiting till you choose the item you want from the grid view
Write-Host "$user_choice is going to be the VM"
I wouldn't try to make it with System.windows.forms utilities as i mentioned in my comment, unless you want to present the form more "good looking".
If you don't want to go for a graphical menu, but rather a console menu, you could use this function below:
function Show-Menu {
Param(
[Parameter(Position=0, Mandatory=$True)]
[string[]]$MenuItems,
[string] $Title
)
$header = $null
if (![string]::IsNullOrWhiteSpace($Title)) {
$len = [math]::Max(($MenuItems | Measure-Object -Maximum -Property Length).Maximum, $Title.Length)
$header = '{0}{1}{2}' -f $Title, [Environment]::NewLine, ('-' * $len)
}
# possible choices: digits 1 to 9, characters A to Z
$choices = (49..57) + (65..90) | ForEach-Object { [char]$_ }
$i = 0
$items = ($MenuItems | ForEach-Object { '{0} {1}' -f $choices[$i++], $_ }) -join [Environment]::NewLine
# display the menu and return the chosen option
while ($true) {
cls
if ($header) { Write-Host $header -ForegroundColor Yellow }
Write-Host $items
Write-Host
$answer = (Read-Host -Prompt 'Please make your choice').ToUpper()
$index = $choices.IndexOf($answer[0])
if ($index -ge 0 -and $index -lt $MenuItems.Count) {
return $MenuItems[$index]
}
else {
Write-Warning "Invalid choice.. Please try again."
Start-Sleep -Seconds 2
}
}
}
Having that in place, you call it like:
# get a list if iso files (file names for the menu and full path names for later handling)
$isoFiles = Get-ChildItem -Path 'D:\IsoFiles' -Filter '*.iso' -File | Select-Object Name, FullName
$selected = Show-Menu -MenuItems $isoFiles.Name -Title 'Please select the ISO file to use'
# get the full path name for the chosen file from the $isoFiles array
$isoToUse = ($isoFiles | Where-Object { $_.Name -eq $selected }).FullName
Write-Host "`r`nYou have selected file '$isoToUse'"
Example:
Please select the ISO file to use
---------------------------------
1 Win10.iso
2 Win7.iso
3 Win8.iso
Please make your choice: 3
You have selected file 'D:\IsoFiles\Win8.iso'

powershell script removing files from the first of the month, instead of keeping them

$RollingYear = (Get-Date).AddDays(-365)
$Rolling30Days = (Get-Date).AddDays(-30)
#Clean-Up Old Backup Files
Get-ChildItem 'D:\Server_Backup\' | ForEach-Object {
if ( $_.LastWriteTime.AddDays(-365) -lt $RollingYear) {
Write-Host "I want to remove files older than a year"
Remove-Item
} Elseif ( $_.LastWriteTime.AddDays(-30) -lt $Rolling30Days -and $_.LastWriteTime.Date -ne (Get-Date -Year $_.LastWriteTime.Year, -Month $_.LastWriteTime.Month -Day 1)) {
Write-Host "I want to remove files older than 1 month, but not the first of the month"
Remove-Item
} Else {
Write-Host 'Nothing to remove'
}
}
This should keep files from the first of the month of anything older than 30 days and remove the rest. Currently it is removing the 1st of the month and keeping the rest. What did I do wrong?
your logic confused me [blush], so i rewrote it using day counts instead of datetime comparisons.
$SourceDir = $env:TEMP
$Today = (Get-Date).Date
$YearInDays = 365
$MonthInDays = 30
#Clean-Up Old Backup Files
Get-ChildItem -LiteralPath $SourceDir -File |
ForEach-Object {
$DaysOld = ($Today - $_.LastWriteTime).Days
if ($DaysOld -gt $YearInDays)
{
''
'LWT = {0}' -f $_.LastWriteTime
'File age in days = {0}' -f $DaysOld
Write-Host "I want to remove files older than a year"
Remove-Item $_.FullName -WhatIf
}
Elseif ($DaysOld -gt $MonthInDays -and
$_.LastWriteTime.Day -ne 1)
{
''
'LWT = {0}' -f $_.LastWriteTime
'File age in days = {0}' -f $DaysOld
Write-Host "I want to remove files older than 1 month, but not the first of the month"
Remove-Item $_.FullName -WhatIf
}
Else
{
''
'LWT = {0}' -f $_.LastWriteTime
'File age in days = {0}' -f $DaysOld
Write-Host 'Nothing to remove'
}
}
output ...
LWT = 2015-11-03 6:54:02 PM
File age in days = 1276
I want to remove files older than a year
What if: Performing the operation "Remove File" on target "C:\Temp\FXSAPIDebugLogFile.txt".
LWT = 2019-03-04 12:45:30 PM
File age in days = 59
I want to remove files older than 1 month, but not the first of the month
What if: Performing the operation "Remove File" on target "C:\Temp\Itunes_Default-Rating_Set.ps1_2019-05-03.log".
LWT = 2019-03-01 12:44:23 PM
File age in days = 62
Nothing to remove
LWT = 2015-11-03 9:35:03 PM
File age in days = 1276
I want to remove files older than a year
What if: Performing the operation "Remove File" on target "C:\Temp\qtsingleapp-fmlast-93b-1-lockfile".
LWT = 2019-05-03 6:43:11 AM
File age in days = 0
Nothing to remove

Non-Terminating Exception in Folder Deletion Script

I've written a Powershell script that would periodically delete folders on my machine.
The algorithm is as follows:
Drill down into each directory structure to the lowest subfolders
Check the creation date of the subfolder
If it's 14 days old, or older, delete it
LOG EVERYTHING (not part of the algorithm, just good practise)
When running, it operates exactly as expected...
... Except it throws the following, non-terminating exception:
Get-ChildItem : Could not find a part of the path 'C:\foo\baz'.
At C:\src\CoreDev\Trunk\Tools\BuildClean script\buildclean.ps1:55 char:15
+ Get-ChildItem <<<< -recurse -force |
+ CategoryInfo : ReadError: (C:\foo\baz:String) [Get-ChildItem],
DirectoryNotFoundException
+ FullyQualifiedErrorId : DirIOError,Microsoft.PowerShell.Commands.GetChil
dItemCommand
Why is this happening? More importantly, how can I remove it, and will it cause an issue?
The script is as follows:
# folderclean.ps1
# This script will remove each leaf node of a directory, provided that leaf is over
# 14 days old.
# CONSTANT DECLARATIONS
# testing (run on my local machine)
$proj_loc = "C:\foo", "C:\bar"
$logpath = "C:\Logs\BuildClean\$(Get-Date -format yyyyMMdd).log"
function Write-ToLogFile {
param ([string]$stringToWrite)
Add-Content $logpath -value $stringToWrite
}
# Function to check if a folder is a leaf folder.
# First, retrieve the directory $item is pointing to
# Then, create a list of children of $item that are folders
# If this list is either empty or null, return $true
# Otherwise, return $false
function Folder-IsLeaf($item) {
$ary = Get-ChildItem $item -force | ?{ $_.PSIsContainer }
if (($ary.length) -eq 0 -or $ary -eq $null) {
return $true
}
return $false
}
# Deletes leaf folders that are older than a certain threshhold.
# Get a list of children of the folder, where each child is a folder itself and
# was created over 14 days ago and the folder is a leaf
# For each of these children, delete them and increment $folderCount
# Get a list of children of the folder, where each child is a folder itself and
# was last modified over 14 days ago and the folder is a leaf
# For each of these children, delete them and increment $folderCount
function Remove-LeafFolders($path) {
$createdCount = 0
$modifiedCount = 0
Write-ToLogFile "Operation started at $(Get-Date -format "dd/MM/yyyy hh:mm:ss.fff")"
Write-ToLogFile "Looking in $proj_loc"
Write-ToLogFile ""
$start = $(Get-Date)
$proj_loc |
Get-ChildItem -recurse -force |
?{
$_.PSIsContainer -and ($_.CreationTime).AddDays(15) -lt $(Get-Date) -and $(Folder-IsLeaf $_.FullName) -eq $true
} | %{
$formattedDate = $($_.CreationTime).ToString("dd/MM/yyyy hh:mm:ss");
Write-ToLogFile "Folder $($_.FullName) is being removed; created: $formattedDate"
Remove-Item $_.FullName -recurse;
$createdCount += 1
}
$end = $(Get-Date)
$elapsed = $end - $start
Write-ToLogFile "Operation completed at $(Get-Date -format "dd/MM/yyyy hh:mm:ss.fff")."
Write-ToLogFile "Folders removed: $createdCount"
Write-ToLogFile "Time elapsed: $(($elapsed).TotalMilliseconds) ms"
Write-ToLogFile "-------------------------------"
}
Remove-LeafFolders($proj_loc)
I found this other StackOverflow question, and, after looking through the answer, I realised that the problem was the pipeline. So, I changed my code as follows:
...
$leafList = $proj_loc |
Get-ChildItem -recurse -force |
?{
$_.PSIsContainer -and ($_.CreationTime).AddDays(15) -lt $(Get-Date) -and $(Folder-IsLeaf $_.FullName) -eq $true
}
Foreach ($folder in $leafList)
{
$formattedDate = $($folder.CreationTime).ToString("dd/MM/yyyy hh:mm:ss");
Write-ToLogFile "Folder $($folder.FullName) is being removed; created: $formattedDate"
Remove-Item $folder.FullName -recurse;
$createdCount += 1
}
...
I created a few local folders and screwed around with them. No exceptions cropped up, so this appears to have worked:
Operation started at 10/12/2012 05:16:18.631
Looking in C:\foo C:\bar
Folder C:\foo\baz is being removed; created: 09/01/2010 02:00:00
Folder C:\bar\baz3\recursion is being removed; created: 01/01/2008 01:00:00
Operation completed at 10/12/2012 05:16:18.748.
Folders removed: 2
Time elapsed: 33.0033 ms
-------------------------------
Operation started at 10/12/2012 05:41:59.246
Looking in C:\foo C:\bar
Folder C:\foo\baz2\NewFolder is being removed; created: 10/10/2010 10:10:10
Folder C:\bar\baz3\barbar is being removed; created: 20/11/2012 05:37:38
Operation completed at 10/12/2012 05:41:59.279.
Folders removed: 2
Time elapsed: 21.0021 ms
-------------------------------
I think it would be easier to accomplish this sort of recursive deletion using a bottom-up approach rather than a top-down which is what Get-ChildItem gives you by default. Try this instead:
$proj_loc |
Get-ChildItem -recurse -force -Name | sort -desc | Get-Item |
? { ....
}

creating powershell script to backup a file and append the date

Currently I have a one line batch file to back up a file. I run it manually when I need to back up a file. The only thing I would like to add to it is the current date. Here is what I have:
xcopy /W /Y ACTIVE.DB ACTIVE.DB.BACKUP
the destination file should simply be ACTIVE.DB.BACKUP.YYYYMMDD. How would I go about creating a script that will allow me to double click on it from Windows Explorer and make the xcopy happen?
Just to point out that you can do this with Copy-Item e.g.:
Set-Location $path
Copy-Item ACTIVE.DB "ACTIVE.DB.$(get-date -f yyyyMMdd)" -Force -Confirm
If you're going for robust then I'd use robocopy.exe.
You can customize your filename by embedding a formatted [datetime]::now in the file name in PowerShell like so:
xcopy /W /Y ACTIVE.DB "ACTIVE.DB.BACKUP.$([datetime]::now.ToString('yyyy-MM-dd'))"
If the line feels busy and unmaintainable, you can refactor it to multiple lines:
$now = [datetime]::now.ToString('yyyy-MM-dd')
xcopy /W /Y ACTIVE.DB "ACTIVE.DB.BACKUP.$now"
To get double-click execution, I usually make a batch file that runs the PowerShell command as described here:
Set up PowerShell Script for Automatic Execution
I just made a Daily/Weekly/Monthly/Quarterly/Yearly backup script in Powershell this month, and hope it helps.
This DWMQY backup scenario is to zip a source folder to a date-named zip file, then keep the zips of:
last 7 days
4 weeks (each Friday's)
6 months (the last Friday's of each month)
4 quarters (the last month's of quarter)
2 years (the last quarter's of year).
Running as scheduled task on daily basis, it puts the zips into a target folder which is also a Microsoft OneDrive's local folder, so the zips also being remotely sync'd to OneDrive server. Those outdated (non-Friday daily or non-last-DWMQY) zips will be moved to a non-remotely-sync'd folder.
It's March 5, 2016 today, the following zips should be in the target folder:
7 days: 160304-160229-160227
4 weeks: 160304, 160226, 160219,160212
6 months: 160226, 160129, 161225, 151127, 151025, 150925
4 quarters: 151225, 150925,150626,150327
2 years: 151225, 141226
So there will be 23 zips (actually less since the dups among DWMQY), our files are 250 text documents which is 0.4 GB after zipping, so it's 23*0.4 = 9.2 GB in total, which is less than OneDrive free 15 GB quota.
For large source data, 7-zip can be used, which provides maximum 16 mil TB zip size. For directly backup folders instead of zips, haven't tried. Guessing it's a transferable procedure from the current zip way.
# Note: there are following paths:
# 1. source path: path to be backed up.
# 2. target path: current zips stored at, which is also a remote-sync pair's local path.
# 3. moved-to path: outdated zips to be moved in this non-sync'able location.
# 4. temp path: to copy the source file in to avoid zip.exe failing of compressing them if they are occupied by some other process.
# Function declaration
. C:\Source\zipSaveDated\Functions.ps1
# <1> Zip data
$sourcePath = '\\remoteMachine1\c$\SourceDocs\*'
$TempStorage = 'C:\Source\TempStorage'
$enddate = (Get-Date).tostring("yyyyMMdd")
$zipFilename = '\\remoteMachine2\d$\DailyBackupRemote\OneDrive\DailyBackupRemote_OneDrive\' + $enddate + '_CompanyDoc.zip'
Remove-Item ($TempStorage + '\*') -recurse -Force
Copy-Item $sourcePath $TempStorage -recurse -Force
Add-Type -A System.IO.Compression.FileSystem
[IO.Compression.ZipFile]::CreateFromDirectory($TempStorage, $zipFilename)
# <2> Move old files
$SourceDir = "\\remoteMachine2\d$\DailyBackupRemote\OneDrive\DailyBackupRemote_OneDrive"
$DestinationDir = "\\remoteMachine2\d$\DailyBackupRemote\bak" # to store files moved out of the working folder (OneDrive)
$KeepDays = 7
$KeepWeeks = 4
$KeepMonths = 6
$KeepQuarters = 4
$KeepYears = 2
# <2.1>: Loop files
$Directory = $DestinationDir
if (!(Test-Path $Directory))
{
New-Item $directory -type directory -Force
}
$files = get-childitem $SourceDir *.*
foreach ($file in $files)
{ # L1
# daily removal will not remove weekly copy, 7
If($file.LastWriteTime -lt (Get-Date).adddays(-$KeepDays).date `
-and $file.LastWriteTime.DayOfWeek -NotMatch "Friday" `
)
{
Move-Item $file.fullname $Directory -force
}
} # L1 >>
$files = get-childitem $SourceDir *.*
foreach ($file in $files)
{ # L1
# weekly removal will not remove monthly copy, 4
If($file.LastWriteTime -lt (Get-Date).adddays(-$KeepWeeks * 7).date `
-and (Get-LastFridayOfMonth ($file.LastWriteTime)).Date.ToString("yyyyMMdd") -NotMatch $file.LastWriteTime.Date.ToString("yyyyMMdd")
)
{
Move-Item $file.fullname $Directory -force
}
} # L1 >>
$files = get-childitem $SourceDir *.*
foreach ($file in $files)
{ # L1
# monthly removal will not remove quarterly copy, 6
If($file.LastWriteTime.Month -lt ((Get-Date).Year - $file.LastWriteTime.Year) * 12 + (Get-Date).Month - $KeepMonths `
-and $file.LastWriteTime.Month -NotIn 3, 6, 9, 12
)
{
Move-Item $file.fullname $Directory -force
}
} # L1 >>
$files = get-childitem $SourceDir *.*
foreach ($file in $files)
{ # L1
# quarterly removal will not remove yearly copy, 4
If($file.LastWriteTime.Month -lt ( (Get-Date).Year - $file.LastWriteTime.Year) * 12 + (Get-Date).Month - $KeepQuarters * 3 `
-and $file.LastWriteTime.Month -NotIn 12
)
{
Move-Item $file.fullname $Directory -force
}
} # L1 >>
$files = get-childitem $SourceDir *.*
foreach ($file in $files)
{ # L1
# yearly removal will just go straight ahead. 2
If($file.LastWriteTime.Year -lt (Get-Date).Year - $KeepYears )
{
Move-Item $file.fullname $Directory -force
}
} # L1 >>
<Functions.ps1>
function Get-TimesResult3
{
Param ([int]$a,[int]$b)
$c = $a * $b
Write-Output $c
}
function Get-Weekday {
param(
$Month = $(Get-Date -format 'MM'),
$Year = $(Get-Date -format 'yyyy'),
$Days = 1..5
)
$MaxDays = [System.DateTime]::DaysInMonth($Year, $Month)
1..$MaxDays | ForEach-Object {
Get-Date -day $_ -Month $Month -Year $Year |
Where-Object { $Days -contains $_.DayOfWeek }
}
}
function Get-LastFridayOfMonth([DateTime] $d) {
$lastDay = new-object DateTime($d.Year, $d.Month, [DateTime]::DaysInMonth($d.Year, $d.Month))
$diff = ([int] [DayOfWeek]::Friday) - ([int] $lastDay.DayOfWeek)
if ($diff -ge 0) {
return $lastDay.AddDays(- (7-$diff))
}
else {
return $lastDay.AddDays($diff)
}
}