Powershell Check the folder structure exists or not - powershell

i am on a task to upgrading a batch file to powershell.. i have to perform a task that need to check if the folder structure is exist or not. if not create it from where it missing. Also need to send a mail using smtp about the status...
example:
D:\folder\folder1\folder2\folder3
E:\folder\folder1\folder2\folder3
E:\folderA\folderB\FolderC\FolderD\FolderE
if missing only FolderC and Rest create from FolderC\FolderD\FolderE
if missing from FolderB and rest create from FolderB\FolderC\FolderD\FolderE

This function will do what you need, including detailed log. Copy-paste it or save alongside with your script as Test-DirectoryTree.ps1 and use dot-sourcing to load:
$ScriptDir = Split-Path $script:MyInvocation.MyCommand.Path
. (Join-Path -Path $ScriptDir -ChildPath 'Test-DirectoryTree.ps1')
Usage:
# Array of paths to check
$Paths = #(
'D:\folder\folder1\folder2\folder3',
'E:\folder\folder1\folder2\folder',
'E:\folderA\folderB\FolderC\FolderD\FolderE'
)
# Store function output in $Log variable
# W\o "Create" switch function will only report missing directories
$Log = $Paths | Test-DirectoryTree -Create
# Send email
Send-MailMessage -SmtpServer 'mail.company.com' -From 'script#company.com' -To 'admin#company.com' -Subject 'Folder status' -Body $Log
Test-DirectoryTree function:
function Test-DirectoryTree
{
[CmdletBinding()]
Param
(
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
[ValidateNotNullOrEmpty()]
[string[]]$Paths,
[switch]$Create
)
Begin
{
# Set path separator
$Separator = '\'
# Init array to hold log
$Log = #()
}
Process
{
# For every path in array
foreach ($Path in $Paths){
# Init array to store existing paths
$Tree = #()
# Split path
foreach ($Dir in $Path.Split($Separator)){
# If not first element
if($Tree)
{
# Build path for current dir to check
$CurrDir = Join-Path -Path ($Tree -join $Separator) -ChildPath $Dir
}
else # If not first element
{
# Check if root dir exist
if(!(Test-Path -LiteralPath $Dir -PathType Container) -and [System.IO.Path]::IsPathRooted($Dir))
{
Write-Error "Root folder '$Dir' is not valid!"
break
}
else
{
# Build path for current dir to check
$CurrDir = $Dir
}
}
# If current dir not exist
if(!(Test-Path -LiteralPath $CurrDir -PathType Container))
{
# Write message to log
$Log += "Folder doesn't exist: $CurrDir"
# If we asked to create missing dirs
if($Create)
{
# Try to create dir
try
{
New-Item -ItemType Directory -Path $CurrDir -ErrorAction Stop | Out-Null
$Log += "Folder created: $CurrDir"
}
catch
{
$Log += "Failed to create folder: $CurrDir"
}
}
}
# If current dir exist, do nothing and add it to existing paths
$Tree += $Dir
}
}
}
End
{
# Return log
return $Log
}
}

This could be more beautiful but.. Here it goes, there are of course many ways to do this depending on exactly how you want to use it.
$SmtpServer = '192.168.1.2' #Replace this with IP adress to your SMTP-server
$Body='' #Two single quotation marks
$path = Read-Host 'Enter Path (Type Exit to quit)'
While ($path -ne 'Exit') {
IF (Test-Path $path) {
$Body += "$path already exists `n" #Adds $path to $Body and breaks line
}
ELSE {
New-Item $path -ItemType directory
$Body += "$path was created `n" #Adds $path to $Body and breaks line
}
$path = Read-Host 'Enter Path (Type Exit to quit)'
}
IF($Body -ne '') {
Send-Mailmessage -SmtpServer $SmtpServer -Subject "Folder status" -Body $Body
}

Related

Can someone help to add email function correctly

I am adding an email function to send an email if the file uploads success or failure, but when I upload the file, it sends a message as I write in the body for success but I am not sure if it captures the error function as well in the email.
I upload the file as per the naming convention and it moved successfully.
When I tried to upload the wrong file through this, it does not capture the catch statement in the log file.
I want to capture the backup copy name in logs as well.
Got an email on the successful event but didn't get an email on the catch statement.
Please see the below code.
$Source = 'c:\uploadtool\' # Source Location
$RetailSource = 'Retail P&C Sales Intelligence\*'
$GroupSource = 'Group P&C Sales Intelligence\*'
$RetailDest = 'D:\ToolUpload\Retail-EIP' # 1st Destination Location
$GroupDest = 'D:\ToolUpload\Group-EIP' # 2nd Destination location
$ArchiveData = 'D:\Backup\backup_{0:yyyyMMddHHmm}' -f (Get-Date)
$LogFolder = 'D:\logs'
# because of your wish to get a Table-style log, use CSV format you can open in Excel
$LogFile = 'D:\logs\uploadlog_{0:yyyyMMdd}.csv'-f (Get-Date)
$Sourcetest = Test-Path -Path '$RetailSource','$GroupSource' -PathType Leaf
$SmtpServer ='essexlake1.mail.protection.outlook.com' # SMTP Server name
$SmtpPort='25'
$Subject='File Upload Status'
$To="####domain.com"
$From="#####domain.com"
# make sure the output LogFolder exist
# by adding the -Force switch there is no need to use Test-Path first, because if
# the folder already exists, the cmdlet will return the DirectoryInfo of that,
# otherwise it will create a new folder. Since we dont want output, we use $null = ..
$null = New-Item -Path $LogFolder -ItemType Directory -Force
# loop through the files in the source folder and collect the outputted objects
$result = Get-ChildItem -Path $Sourcetest -Include '*Group-EIP*', '*Retail-EIP*' -File -Force -Recurse |
ForEach-Object {
Write-Host "Processing file '$($_.FullName)'"
# create an object with (for now) 3 empty properties
$out = $_ | Select-Object #{Name = 'Date'; Expression = {(Get-Date)}},
#{Name = 'Source'; Expression = {$_.FullName}},
#{Name = 'FileSize'; Expression = {$_.Length}},
Destination, # depends on the file name
#{Name = 'Archive'; Expression = {$ArchiveData}}, # initialize to Not Applicable
Result
# depending on its name, get the correct destination folder
$destFolder = if($_.Name -match "Retail-EIP") { $RetailDest } else { $GroupDest }
# create the backup destination folder if it didn't already exist
# the first file in column 'Source' is now responsible for creating the backup folder
$null = New-Item -Path $destFolder -ItemType Directory -Force
# get the full path and filename for the destination
$existingFile = Join-Path -Path $destFolder -ChildPath $_.Name
# add the destination folder to the output object
$out.Destination = $destFolder
try {
# if a file with that name already exists in the destination, move it to the Archive folder
if (Test-Path -Path $existingFile -PathType Leaf) {
# create the Archive folder if it didn't already exist
$null = New-Item -Path $ArchiveData -ItemType Directory -Force
Move-Item -Path $existingFile -Destination $ArchiveData -ErrorAction Stop
# add the archived file to the output object
$out.Archive = $existingFile
Write-Host "File '$existingFile' has been backed-up to '$ArchiveData'"
}
# next move the file from the source folder to its destination (either $RetailDest or $GroupDest)
$_ | Move-Item -Destination $destFolder -ErrorAction Stop
$out.Result = 'OK'
Write-Host "File '$($_.FullName)' has been moved to '$destFolder'"
$Body=" The File '$($_.FullName)' has been moved to '$destFolder"
Send-MailMessage -SmtpServer $SmtpServer -Port $Port -From $From -To $To -Subject $Subject -Body $Body
}
catch {
# ouch.. something went horribly wrong on a Move-Item action
Write-Warning "An error occurred: $_.Exception.Message"
$out.Result = "Error: $($_.Exception.Message)" | Add-Content -Path $LogFile -Force
}
# output the object so it gets collected in variable $result
$out
}
# now you can save the results as structured CSV file to open in Excel
$result | Export-Csv -Path $LogFile -UseCulture -NoTypeInformation -Append
# and display on screen using Out-GridView as the data will probably be too wide for Format-Table
$result | Out-GridView -Title 'Backup results
'
It's not going to send an email on-error because Send-MailMessage is the last statement in the Try{...} block. If anything errors before that the statement Send-MailMessage won't run.
If it were me, and from this starting point I'd populate $Body respective to the outcome (success/fail) and send the email afterward. Not only would this send with correct information regardless but avoids having a second Send-MailMessage command in the catch block. Obviously I can't rig up a test of such a big code segment, but it might look something like:
$Source = 'c:\uploadtool\' # Source Location
$RetailSource = 'Retail P&C Sales Intelligence\*'
$GroupSource = 'Group P&C Sales Intelligence\*'
$RetailDest = 'D:\ToolUpload\Retail-EIP' # 1st Destination Location
$GroupDest = 'D:\ToolUpload\Group-EIP' # 2nd Destination location
$ArchiveData = 'D:\Backup\backup_{0:yyyyMMddHHmm}' -f (Get-Date)
$LogFolder = 'D:\logs'
# because of your wish to get a Table-style log, use CSV format you can open in Excel
$LogFile = 'D:\logs\uploadlog_{0:yyyyMMdd}.csv'-f (Get-Date)
$Sourcetest = Test-Path -Path '$RetailSource','$GroupSource' -PathType Leaf
#Email Params:
$EmailParams = #{
SmtpServer ='essexlake1.mail.protection.outlook.com' # SMTP Server name
Port ='25'
Subject ='File Upload Status'
To ="####domain.com"
From ="#####domain.com"
}
# make sure the output LogFolder exist
# by adding the -Force switch there is no need to use Test-Path first, because if
# the folder already exists, the cmdlet will return the DirectoryInfo of that,
# otherwise it will create a new folder. Since we dont want output, we use $null = ..
$null = New-Item -Path $LogFolder -ItemType Directory -Force
# loop through the files in the source folder and collect the outputted objects
$result =
Get-ChildItem -Path $Sourcetest -Include '*Group-EIP*', '*Retail-EIP*' -File -Force -Recurse |
ForEach-Object {
Write-Host "Processing file '$($_.FullName)'"
# create an object with (for now) 3 empty properties
$out = $_ |
Select-Object #{Name = 'Date'; Expression = {(Get-Date)}},
#{Name = 'Source'; Expression = {$_.FullName}},
#{Name = 'FileSize'; Expression = {$_.Length}},
Destination, # depends on the file name
#{Name = 'Archive'; Expression = {$ArchiveData}}, # initialize to Not Applicable
Result
# depending on its name, get the correct destination folder
$destFolder = if($_.Name -match "Retail-EIP") { $RetailDest } else { $GroupDest }
# create the backup destination folder if it didn't already exist
# the first file in column 'Source' is now responsible for creating the backup folder
$null = New-Item -Path $destFolder -ItemType Directory -Force
# get the full path and filename for the destination
$existingFile = Join-Path -Path $destFolder -ChildPath $_.Name
# add the destination folder to the output object
$out.Destination = $destFolder
try
{ # if a file with that name already exists in the destination, move it to the Archive folder
if (Test-Path -Path $existingFile -PathType Leaf) {
# create the Archive folder if it didn't already exist
$null = New-Item -Path $ArchiveData -ItemType Directory -Force
Move-Item -Path $existingFile -Destination $ArchiveData -ErrorAction Stop
# add the archived file to the output object
$out.Archive = $existingFile
Write-Host "File '$existingFile' has been backed-up to '$ArchiveData'"
}
# next move the file from the source folder to its destination (either $RetailDest or $GroupDest)
$_ | Move-Item -Destination $destFolder -ErrorAction Stop
$out.Result = 'OK'
Write-Host "File '$($_.FullName)' has been moved to '$destFolder'"
$Body = " The File '$($_.FullName)' has been moved to '$destFolder"
}
catch
{ # ouch.. something went horribly wrong on a Move-Item action
$Body = " Error occured trying to move the file '$($_.FullName)' to '$destFolder. `n$($_.Exception.Message)"
Write-Warning "An error occurred: $_.Exception.Message"
$out.Result = "Error: $($_.Exception.Message)" | Add-Content -Path $LogFile -Force
}
Send-MailMessage #EmailParams -Body $Body
# output the object so it gets collected in variable $result
$out
}
# now you can save the results as structured CSV file to open in Excel
$result | Export-Csv -Path $LogFile -UseCulture -NoTypeInformation -Append
# and display on screen using Out-GridView as the data will probably be too wide for Format-Table
$result | Out-GridView -Title 'Backup results'
Forgive the reformat, that was for my own readability. I also added splatting to the email command. You were setting all those parameter vars early in the script any way...
Note: for all other parts of this question I think the straight forward answer is you have to add the instructions to tell the program what you want it to do. If you want to log on a specific condition, figure out where that's going to happen and add an Add-Content command etc...

List all files that were moved in an email Body - Powershell

Trying to accomplish the following:
1)Move files from multiple sources into multiple destinations.
Therefore i listed sources under a SOURCE column, and destinations under a DESTINATION column (WORKING)
2)Send an email with a list of files that were moved and the destination (Not working)
Param (
[string]$SMTPServer = "XXX.XX.xXX",
[string]$From = "from#email.com",
[string]$To = "to#email.com",
[string]$Subject = "New File"
)
Import-Csv -Path "C:\moveallfiles.csv" -ErrorAction Stop | foreach {
if (-not (Test-Path -Path $_.Destination))
{
# Create directory if needed
New-Item -ItemType directory -Path $_.Destination -WhatIf
}
# Copy file
$MoveFileprocess = Move-Item -Path $_.Source -Destination $_.Destination -force -PassThru
}
$SMTPMessage = #{
To = $To
From = $From
Subject = "$Subject"
Smtpserver = $SMTPServer
}
$SMTPBody = "`nThe following files have recently been added `n
$MoveFileprocess `n"
Send-MailMessage #SMTPMessage -Body $SMTPBody
Right now its listing all the files in one single line, hard to read
I was wondering if theres a way to send the body email as
File 1 moved to Destination 1
File 2 moved to Destination 2
and so on...
You were pretty close. Try this:
Param (
[string]$SMTPServer = "XXX.XX.xXX",
[string]$From = "from#email.com",
[string]$To = "to#email.com",
[string]$Subject = "New File"
)
$SMTPBody = "`nThe following files have recently been added `n"
Import-Csv -Path "C:\moveallfiles.csv" -ErrorAction Stop | foreach {
if (-not (Test-Path -Path $_.Destination)){
# Create directory if needed
New-Item -ItemType directory -Path $_.Destination
}
If((Get-Item $_.Source).LastWriteTime -gt (Get-Item $_.Destination).LastWriteTime){
Move-Item -Path $_.Source -Destination $_.Destination -force
$SMTPBody += "$($_.Source) moved to $($_.Destination)`n"
}Else{
Write-Warning "Skipped overwriting newer $($_.Destination)"
}
}
$SMTPMessage = #{
To = $To
From = $From
Subject = "$Subject"
Smtpserver = $SMTPServer
}
Send-MailMessage #SMTPMessage -Body $SMTPBody
Note that Move-Item -PassThru returns the affected object, not a string. I took out the -WhatIf parameter for the New-Item command, indented the foreach{} loop and made indenting and brackets consistent.

Powershell - Trouble passing Validateset parameters into ForEach-Object, getting prompt

So I'm new to PowerShell, and I'm trying to get this function to work.
I have 2 ValidateSet arrays with 3 parameters. These parameters are supposed to change the file path and copy them over from one server to another. For some reason, I keep getting the command prompt for the parameters instead of them passing through. I'm guessing it's an issue with the ForEach-Object, but I'm at a loss. It IS, however, working for the $ArchivePath. I'm new, so please be gentle... TIA
param(
[Parameter(Mandatory = $true)]
[ValidateSet("One", "Two", "Three")]
[string[]]$Channel
,[Parameter(Mandatory = $true)]
[Alias('Phase')]
[ValidateSet("Devl", "Test", "Prod")]
[string[]]$Phase
,[Parameter(Mandatory = $false)]
[string]$FilenameFilter = '.csv'
,[Parameter(Mandatory = $false)]
[switch]$CreateTrigger
)
function ExitWithCode { param($exitcode) $host.SetShouldExit($exitcode); exit $exitcode }
$exitcode = 0
try {
# Get a list of files on the host server.
#
$files = Get-ChildItem -File -Path "\\ServerName\d\Extract\$Phase\FileTransfer\$Channel\Outbound"
# Destination directory.
#
$LocalPath = "\\ServerName\d\Extract\$Phase\FileTransfer\$Channel\Outbound" #for testing
# Set up folder name for Archive server. Formated as YYYYMMDDTHHMMSS YYYYMMDD --> Var_Date, 'T' --> Var_Constant & HHMMSS --> Var_Time
#
$Var_Date = get-date -UFormat "%Y-%m-%d"
$Var_Constant = 'T'
$Var_Time = get-date -UFormat "%H-%M-%S"
$Var_Fulldate = $Var_Date + $Var_Constant + $Var_Time
$ArchivePath = $env:USERPROFILE + "\Desktop\$Channel\$Var_Fulldate" #For testing
New-Item -Type Directory -Path $ArchivePath
if (-not (Test-Path -Path $ArchivePath -ErrorAction SilentlyContinue)) { $ArchivePath = $Env:TEMP }
#Look for files in Outbound directory and remove
Get-ChildItem -File -Path $LocalPath | ForEach-Object { Copy-Item $_.FullName } #Using copy instead of remove for test
$FileCount = 0
Write-Output Try2 #for testing
pause #for testing
foreach ($file in $files) {
if ((-not $file.IsDirectory) -and ($File.FullName -match $FilenameFilter)) {
$localfilename = $LocalPath + $file.Name
if (Test-Path $localfilename) { Copy-Item $localfilename }
try {
Copy-Item -Path $(Join-Path -Path $LocalPath -ChildPath $file.Name) -Destination $ArchivePath
#Remove files from outbound since they've been archived
#
#Remove-Item -Path $file.FullName
"Retrieved file $file"
$FileCount++
}
catch {
Write-Output Try13 #for testing
$exitcode = 13
"failed to retrieve $file"
}
finally {
$error.Clear()
}
}
}
}
catch {
Write-Output Try3
$exitcode = 14
}
finally {
Write-Output Try4
$error.Clear()
}
if ($CreateTrigger -and ($exitcode -eq 0) -and ($FileCount -gt 0)) {
New-Item -Path "$LocalPath\Trigger_File.trg" -ItemType File | Out-Null
}
#ExitWithCode $exitcode # take out for testing
The output:
PS C:\Users\me> \\Server\blah\USERS\me\My Documents\Folder\Get-FileName_t4.ps1
cmdlet Get-FileName_t4.ps1 at command pipeline position 1
Supply values for the following parameters:
Channel[0]: Three
Channel[1]:
Phase[0]: Devl
Phase[1]:
Directory: C:\Users\me\Desktop\Three
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 11/22/2019 12:17 PM 2019-11-22T12-17-23
Try2
Press Enter to continue...:
Retrieved file File1_20191122080912.csv
Retrieved file File2_20191122080922.csv
Retrieved file File3_20191122080925.csv
Retrieved file File4_20191122080932.csv
Retrieved file File5_20191122080933.csv
Retrieved file File6_20191122080933.csv
Try4
You are getting prompted because you're not passing in those parameters but Mandatory=$true is set on the arguments you are getting prompted for. Since your session is interactive, it asks you to input the correct values. If you don't want to get prompted, provide the mandatory arguments:
"\\Server\blah\USERS\me\My Documents\Folder\Get-FileName_t4.ps1" -Channel Three -Phase Dev1
A couple of other things I noticed:
You don't need to provide Mandatory=$false, as Mandatory is $false by default
Setting an alias of Phase for the -Phase argument is also redundant

PowerShell Batch ConvertImage

I am working on a PowerShell function that will convert jpg to png. I got that to work. I cannot figure out how to get it to delete the original jpg file after finishing. I have attempted to use the del and remove command but cannot delete the original file because it is still being used in the process. I have also tried to end the process but it ended the whole process when I put it within the foreach loop. Is there a way to get it to end the process so the file can be deleted and then continue through the rest of the images? Below is the code that converts but does not delete. If there is a better way to do this I would like to know were I can improve. Thank you !
function ConvertImage{
param ([string]$path)
$path=Convert-Path . #path to files
if (Test-Path $path)
{
#Load required assemblies and get object reference
[Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") | Out-Null
foreach($file in (ls "$path\*.jpg")){
$convertfile = new-object System.Drawing.Bitmap($file.Fullname)
$newfilname = ($file.Fullname -replace '([^.]).jpg','$1') + ".png"
$convertfile.Save($newfilname, "png")
$file.Fullname
}
}
else
{
Write-Host "Path not found."
}
};ConvertImage -path $args[0]
How Do I use an integer with leading zeroes for the code below:
function ConvertImage{
param ([string]$path)
$Name = Read-Host -Prompt 'Input new name'
$Start = Read-Host -Prompt 'Input start number'
$Ext1 = Read-Host -Prompt 'Input Initial Extension'
$Ext2 = Read-Host -Prompt 'Input Ending Extension'
Write-Host "You input '$Name' and '$Start'"
Write-Host "You input '$Ext1' and '$Ext2'"
$i = "{0:D2}" -f [int]$Start
Get-ChildItem ("*.$Ext1") | %{Rename-Item $_ -NewName ("$Name"+"_"+"$i.$Ext1" -f $i++)}
Get-ChildItem ("*.$Ext2") | %{Rename-Item $_ -NewName ("$Name"+"_"+"$i.$Ext2" -f $i++)}
$path=Convert-Path . #path to files
if (Test-Path $path)
{
#Load required assemblies and get object reference
[Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") | Out-Null
foreach($file in (ls "$path\*.$Ext1")){
$convertfile = new-object System.Drawing.Bitmap($file.Fullname)
$newfilname = ($file.Fullname -replace "([^.]).$Ext1",'$1') + (".$Ext2")
$convertfile.Save($newfilname, "$Ext2")
$file.Fullname
# Dispose file to stop using it
$convertfile.dispose()
# In brackets in the event that the filepath has a space
Remove-Item "$($file.Fullname)"
}
}
else
{
Write-Host "Path not found."
}
};ConvertImage -path $args[0]
Just do a Remove-Item at the end of your foreach.
function ConvertImage{
param ([string]$path)
$path=Convert-Path . #path to files
if (Test-Path $path)
{
#Load required assemblies and get object reference
[Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") | Out-Null
foreach($file in (ls "$path\*.jpg")){
$convertfile = new-object System.Drawing.Bitmap($file.Fullname)
$newfilname = ($file.Fullname -replace '([^.]).jpg','$1') + ".png"
$convertfile.Save($newfilname, "png")
$file.Fullname
# Dispose file to stop using it
$convertfile.dispose()
# In brackets in the event that the filepath has a space
Remove-Item "$($file.Fullname)"
}
}
else
{
Write-Host "Path not found."
}
};ConvertImage -path $args[0]

Powershell script to deploy files with necessary backup

Team,
I'm writing a powershell script to automate one of the manual task we are doing daily. I need expert suggestion and help here as I'm new to powershell scripting.
Requirement:
There is a source, destination and a backup folder.
Source may have diff files and files within multiple folders of source.
eg: source\Login.aspx or source\App_Code\BLogic.vb or source\bin\servr.dll etc.
While copying to destination, my source file has to be checked for existence at destination, if exists then we need to copy the current existing file in destination to backup folder, then copy source to destination.
Below are the scripts that i have tried till now.
Script1:
I'm able to list files which are same but not able to copy those array elements to backup location:
#Declare Source and Destination
$source = Get-ChildItem -Recurse -path \\server1\\e$\ps\src\
$dest = Get-ChildItem -Recurse -path \\server2\\e$\ps\dest\
#lists only objects which are equal and assign to variable
$files=compare-Object -DifferenceObject $source -ReferenceObject $dest -IncludeEqual -ExcludeDifferent
$array = #($files)
$len=$array.length
for ($i=0; $i -lt $array.length; $i++)
{
$array[$i]
}
Script2:
As script1 i was facing problem i tried a silly logic with this script, but i feel this is also having too much manual work :( please help me.
Function cpytest ($s, $d)
{
Copy-Item -Path $s -Destination $d;
}
$n = Read-Host "Enter no of files to be uploaded"
$b = Read-Host "Enter Backup Location for file backups"
for ($i=0;$i -lt $n;$i++)
{
$s = Read-Host "Enter Source with complete file name"
$d = Read-Host "Enter Destination with file name too"
$r = Test-Path $d
If ($r -eq "True")
{
cpytest $d $b
cpytest $s $d
}
Else
{
cpytest $s $d
}
}
Try something like this:
Function BackupAndMoveFile($filePath, $backupPath, $deployPath) {
$fileName = Split-Path $filePath -Leaf
$deployFile = Join-Path $deployPath $fileName
if ((Test-Path $deployFile)) {
$backupFile = Join-Path $backupPath $fileName
Move-Item $deployFile $backupFile -Force
if (!(Test-Path $backupFile)) {
Write-Warning "Can't backup $fileName to $backupFile"
return $false
}
}
Copy-Item $filePath $deployPath -Force
if (!(Test-Path $deployPath)) {
Write-Warning "Can't deploy $fileName to $deployPath"
return $false
}
return $true
}
BackupAndMoveFile 'C:\temp\backup-test.txt' `
'C:\temp\backup' `
'C:\temp\deploy'
It will overwrite anything in the backup directory so you might want to modify to add a timestamp.