How to manage transition from one year to another in powershell - powershell

I've this list of directories to ZIP :
2019_40
2019_41
2019_42
2019_43
2019_44
2019_45
2019_46
2019_47
2019_48
2019_49
2019_50
2019_51
2019_52
2020_01
2020_02
2020_03
2020_04
2020_05
Here my code to zip them. I set the year 2020 for simulation what will happen the next year :
### Set 7Zip excutabe as variable
$7Zip = gci c:\Program* -include '7z.exe' -recurse -ea 4|select -first 1 -expand fullname
# Date
$Year = get-date -UFormat %Y
$WeekNb = get-date -UFormat %V
#Simulation the future
$Year = "2020"
$WeekNb = "02"
$Dir_To_Zip = Get-ChildItem -path "C:\Temp\LOG Script"
Foreach ($element in $Dir_To_Zip )
{
$DirName = $element.Name
$DirNameY = $DirName.Substring(0, $DirName.Length -3 )
$DirNameW = $DirName.Substring($DirName.Length -2)
if ( $DirNameW -lt $WeekNb - 4 )
{
& $7zip a "$element.zip" "$element" }
}
In this state my script is ziping the directories of the year 2020 only, not the 2019.
If I change this line :
if ( $DirNameW -lt $WeekNb - 4 )
by this one
if (( $DirNameY -le $Year -1 ) -or ($DirNameW -lt $WeekNb -4 ))
All directories are zipped

With the -or condition, the $DirNameY was not considered like a string number so I corrected like this :
#Set 7Zip excutabe as variable
$7Zip = gci c:\Program* -include '7z.exe' -recurse -ea 4|select -first 1 -expand fullname
# Date
$Year = get-date -UFormat %Y
$WeekNb = get-date -UFormat %V
# DEBUG pour forcer l annee et le numero de seamine
$Year = "2020"
$WeekNb = "05"
# List files to  Zip
$Dir_To_Zip = Get-ChildItem -path "C:\Temp\LOG Script"
Foreach ($element in $Dir_To_Zip )
{
$DirName = $element.Name
$DirNameY = $DirName.Substring(0, $DirName.Length -3 )
$DirNameW = $DirName.Substring($DirName.Length -2)
$DirNameW = $DirNameW.trimstart('0')
if (( $DirNameY -lt $Year -1 ) -or ($DirNameW -lt $WeekNb -4 ))
{
& $7zip a "$element.zip" "$element" }
}

Related

How to get a result from a function

I'm trying to write a function to calculate either a full ISO date (yyyy-W-d, where W is the ISO week number), or just the ISO week number by itself. My function is based on this.
I have 2 problems with my code. One is that I do not know how extract either of the results I am after as written above. The other problem is that the second parameter doesn't show when I try to call the function.
This is my current code.
Function Get-ISODate {
Param(
[datetime]$Date = (Get-Date),
[bool]$LongFormat
)
$DayOfWeek = $Date.DayOfWeek
If ($DayOfWeek -match "[1-3]") {$Date.AddDays(3)}
$Year = $Date.Year
$Week = $(Get-Culture).Calendar.GetWeekOfYear(($Date),[System.Globalization.CalendarWeekRule]::FirstFourDayWeek, [DayOfWeek]::Monday)
$Day = $Date.Day
If ($LongFormat)
{
Get-ISODate = $Year + '-W' + $Week + '-' + $Day
}
Else
{
Get-ISODate = 'W' + $Week
}
}
My expected results would be,
Get-ISOWeek returns W16, which is the current ISO week at this time of writing.
Get-ISOWeek -LongFormat $true returns 2021-W16-1
Get-ISOWeek -Date '2000-1-1' returns W52
Get-ISOWeek -Date '2000-1-1' -LongFormat $true returns 1999-W52-6
I'm using this link to verifiy my results with regards to the week calculation.
You can read about switch paramenter here.
What Mathias meant is to literally remove Get-ISODate =
The function should look like this:
Function Get-ISODate {
Param(
[datetime]$Date = (Get-Date),
[switch]$LongFormat
)
$DayOfWeek = $Date.DayOfWeek
If ($DayOfWeek -match "[1-3]") {$Date.AddDays(3)}
$Year = $Date.Year
$Week = $(Get-Culture).Calendar.GetWeekOfYear(($Date),[System.Globalization.CalendarWeekRule]::FirstFourDayWeek, [DayOfWeek]::Monday)
$Day = $Date.Day
If ($LongFormat.IsPresent)
{
return "$Year-W$Week-$Day"
}
'W' + $Week
}
# Testing the function
PS /~> Get-IsoDate
W16
PS /~> Get-IsoDate -LongFormat
2021-W16-19
Got this working. Please note that the main issue was that I was trying to call the function incorrectly with "Get-ISOWeek". Monday morning.
I also added .value__ to Day for $Day to get the number instead of the day as "Monday" etc.
Function Get-ISODate {
Param(
[datetime]$Date = (Get-Date),
[bool]$LongFormat
)
$DayOfWeek = $Date.DayOfWeek
If ($DayOfWeek -match "[1-3]") {$Date.AddDays(3)}
$Year = $Date.Year
$Week = $(Get-Culture).Calendar.GetWeekOfYear(($Date),[System.Globalization.CalendarWeekRule]::FirstFourDayWeek, [DayOfWeek]::Monday)
$Day = $Date.DayOfWeek.value__
If ($LongFormat -eq $true)
{
"$Year-W$Week-$Day"
}
Else
{
"W$Week"
}
}
Edit: I realised after posting this, the year was sometimes wrong according to the week number and day of the week. So here is my new version. I have checked the dates here.
Function Get-ISODate {
Param(
[datetime]$Date = (Get-Date),
[switch]$LongFormat
)
[int]$Year = $Date.Year
[int]$Month = $Date.Month
[int]$Day = $Date.DayOfWeek.value__
If ($Day -eq 0) {$Day = 7}
If ($Day -ge 1 -and $Day -le 3) {$Date = $Date.AddDays(3)}
$Week = (Get-Culture).Calendar.GetWeekOfYear($Date, 'FirstFourDayWeek', 'Monday')
Switch ($Week)
{
52 {If ($Day -ge 5 -and $Day -le 7 -and $Month -ne 12) {$Year = $Year - 1} ; Break}
53 {If ($Day -ge 5 -and $Day -le 7 -and $Month -ne 12) {$Year = $Year - 1} ; Break}
1 {If ($Month -eq 12) {$Year = $Year + 1} ; Break}
}
$Week = $Week.ToString('00')
If ($LongFormat.IsPresent)
{
"$Year-W$Week-$Day"
}
Else
{
"W$Week"
}
}

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

copying files from daily folders using Powershell

I am looking to move daily created files each day to another folder. These files are saved to the relevant YYYY\MM\folder each day. Now I have created a way to move these files over using the year/month date function, however because there a number attached to the month, i.e. December looks like "12. December" it becomes a little tricky.
I tried to amend this with an If statement which would assign "a" to the relevant number corresponding with the month however it doesnt work.
$year = (Get-Date).Year
$month = Get-Date -Format "MMMMMMMM"
$day = (Get-Date).Day
$a = ""
If ($month = "January") { $a = "1."}
Elseif ($month = "February") { $a = "2."}
Elseif ($month = "March") { $a = "3."}
Elseif ($month = "April") { $a = "4."}
Elseif ($month = "May") { $a = "5."}
Elseif ($month = "June") { $a = "6."}
Elseif ($month = "July") { $a = "7."}
Elseif ($month = "August") { $a = "8."}
Elseif ($month = "September") { $a = "9."}
Elseif ($month = "October") { $a = "10."}
Elseif ($month = "November") { $a = "11."}
Elseif ($month = "December") { $a = "12."}
$month = Get-Date -Format $a" MMMMMMMM"
Copy-Item -Path F:\BB\$year\$month\Scan.pdf -Destination F:\BB
Any idea how to fix this/where am i going wrong. This is my first time writing in Powershell.
Edit: I am getting an error in the file location it is copying to does not register the difference in the coressponding months. For example the if statement states that if the month is = December a should = 12. but its currently coming up as 1. which should be the case for if it were January
The different forms of the month may as well be repeated in the format string, where
M = month number without leading zeroes
MM = month number with leading zeroes
MMM = abbreviated month name
MMMM = full month name
So:
$Month = Get-Date -f "M. MMMM"
> $Month
12. December
As the format string can contain any letter you can build the source path in one step:
(escaped with a backslash if interfering with a format letter)
$Source = "F:\BB\{0:yyyy\\M. MMMM}\Scan.pdf" -f (Get-Date)
> $Source
F:\BB\2018\12. Dezember\Scan.pdf
But I'm missing the days here?
If you use
$month = Get-Date -Format "MM"
this will get you the month as a number. If I understand what you are trying to achive this should match you source path.
$Date = get-date
$Path = "F:\BB\" + "$($Date.year)" + "\" + "$($Date.month)" + "\"
Copy-Item -Path $Path -Destination F:\BB

Fix moving files into year folder if exist a matching in .txt file

I have files like this
Taxi driver.torrent
Tabu - Gohatto.txt
Troll 2 (1990)..zip
Inside my filelist.txt file I have files named like so
Troll 2 (1990) [BDrip 1080p - H264 - Ita Ac3] Horror, Commedia
Troll 2 (1990) [XviD - Ita Mp3]
Taxi Driver (1976) Mastered..
Tabù - Gohatto (N. Oshima, 1999)
I have just folders like
1976
1990
1999
I want to move files into correct year folder in this way
1976
|__ Taxi driver.torrent
1990
|__ Troll 2 (1990)..zip
1999
|__ Tabu - Gohatto.txt
I use this path, folders
C:\Path
Test4.txt
script_powershell.ps1
I actually test with powershell 5 to move
$movies = #()
(get-content C:\Path\Test4.txt) | foreach($_){
$properties = #{
date = $_.substring($_.IndexOf("(")+1,4)
name = $_.substring(0,$_.IndexOf("("))
}
write-host $date
write-host $name
$movies += New-Object PSObject -Property $properties
}
$torrentFiles = dir $torrentPath
foreach($movie in $movies){
$datePath = "C:\Path\$($movie.date)"
if(-not(test-path $datePath)) {
new-item $datePath -ItemType "directory"
}
$words = ($movie.name -split '\s') | ?{ $_.Length -gt 1}
$significant = $words.Count
foreach($torrentFile in $torrentFiles){
$matchingWords = 0
foreach($word in $words){
if($torrentFile.BaseName -match $word){
$matchingWords += 1
}
}
if($matchingWords -ge $significant){
Move-Item -path $torrentfile -Destination $datePath
}
}
}
EDIT:
This poweshell has many problems. For examples
Caccia al delitto
is moved in 1990 folder...but..Caccia al delitto is 1986..
Inside file text I have
Caccia a Ottobre Rosso (1990) [DivX - Ita Mp3] Guerra [CURA] Russia
Caccia a Ottobre Rosso (1990) [VP9 - Ita Eng Opus] Thriller
I have not a text string for Caccia al delitto (I remove it for test)
$movies = #()
$movieLocation = 'C:\Path'
$torrentPath = '.'
(get-content "$movieLocation\Test4.txt") | foreach($_) {
# Check for braces.
if (-not($_ -match ".*\(.*\).*")) {return}
$properties = #{
date = ($_ -replace ".+?\(.*?(\d{4}).*?\).*", '$1')
name = $_.substring(0, $_.IndexOf("(")).Trim()
}
# Add items that have a 4 digit date.
if ($properties.date -match "^\d{4}$") {
'Name: "' + $properties.name + '" Date: "' + $properties.date + '"'
$movies += New-Object PSObject -Property $properties
}
}
$torrentFiles = dir $torrentPath
foreach ($movie in $movies) {
$datePath = "$movieLocation\$($movie.date)"
if (-not(test-path "$datePath")) {
new-item "$datePath" -ItemType "directory"
}
foreach ($torrentFile in $torrentFiles) {
# Get percentage based on length.
$pc = [int]($movie.name.length / $torrentFile.basename.length * 100)
# Only between 80% and 100% in length.
if ($pc -gt 100) {continue}
if ($pc -lt 80) {continue}
if ($torrentFile.basename -match $movie.name) {
# Items that match.
'Torrent: {0,-40} Date: {1,-5} Match: {2}' -f $torrentFile.basename, $movie.date, $movie.name
if (-not(test-path "$datePath\$torrentfile")) {
Move-Item -LiteralPath "$torrentPath\$torrentfile" -Destination "$datePath"
}
}
}
}
A modest fix with the date using regex.
The name required a trim to remove trailing space.
I added a test-path before move-item in case the file is not found.
Long time since last used Powershell so could be perhaps improved more.
I tested in path . so hope C:\Path works just as well.

Moving files into a file structure on a monthly basis

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
}