Ever need a service that copies a single folder to multiple locations at once? This script will do just that. It will copy a single location to more than one location and even log the outcomes accordingly. Thus, you will be able to set this one up as a task and run it every so often.
Invoke-SHDMoveFiles {
<#
.SYNOPSIS
Copy files from target source folders to a set of target folders.
.DESCRIPTION
Copys from multiple source folders to a select target folders. This allows archiving to occur.
The folders are not auto created. Thus, the folders must exists. The script also adds a log file of any error
messages you see. See notes for more details.
.PARAMETER SourceFolder
[String[]] SourceFolder is an Array of Strings of target folders to move the files from.
.PARAMETER TargetFolder
[String[]] TargetFolder is an Array of strings where the files will be copied to. This is not a one for one ratio. Thus all files will exist inside the targetfolder.
.EXAMPLE
./Invoke-SHDMoveFiles -SourceFolder 'C:\tbc\Tmp\Source Folder\','C:\tbc\tmp\Source Folder 2\' -TargetFolder 'C:\tbc\tmp\Target Folder\','C:\tbc\tmp\Target Folder 2\'
Moves all files from the source folder 1 and 2 to target folders 1 and 2.
.EXAMPLE
./Invoke-SHDMoveFiles -SourceFolder 'C:\tbc\Tmp\Source Folder\' -TargetFolder 'C:\tbc\tmp\Target Folder\','C:\tbc\tmp\Target Folder 2\'
Moves all files from the source folder 1 to target folders 1 and 2.
.EXAMPLE
./Invoke-SHDMoveFiles -SourceFolder 'C:\tbc\Tmp\Source Folder 1\','C:\tbc\Tmp\Source Folder 2\','C:\tbc\Tmp\Source Folder 3\' -TargetFolder 'C:\tbc\tmp\Target Folder\'
Moves all files from the source folder 1, 2, and 3 to the target folder
.EXAMPLE
./Invoke-SHDMoveFiles -SourceFolder 'C:\tbc\Tmp\Source Folder\','C:\tbc\tmp\Source Folder 2\' -TargetFolder 'C:\tbc\tmp\Target Folder\','C:\tbc\tmp\Target Folder 2\' -Recurse
Moves all files under Source folder 1 and 2 to target folders 1 and 2.
.EXAMPLE
./Invoke-SHDMoveFiles -SourceFolder 'C:\tbc\Tmp\Source Folder\' -TargetFolder 'C:\tbc\tmp\Target Folder\','C:\tbc\tmp\Target Folder 2\' -Recurse
Moves all files under source folder 1 to target folders 1 and 2.
.EXAMPLE
./Invoke-SHDMoveFiles -SourceFolder 'C:\tbc\Tmp\Source Folder 1\','C:\tbc\Tmp\Source Folder 2\','C:\tbc\Tmp\Source Folder 3\' -TargetFolder 'C:\tbc\tmp\Target Folder\' -Recurse
Moves all files under source folder 1, 2, and 3 to the target folder
.INPUTS
[String] Folder Paths
.OUTPUTS
No Output
.NOTES
Author: David Bolding
Date: 8/16/2020
Purpose: Moving files around and making archives
Min Powershell Version: 4
This command generates error logs located c:\tbc\SHDMoveFileLog.txt. The error logs structure is broken up in 4 sections seperated with by ;
1;$((Get-Date).tostring());Catch;$($_.Exception)
1 - The placement of the error physically inside the script.
2 - The date and time of the error
3 - What type of error
4 - Information about the error
Run this command inside a scheduled task every 5 minutes to copy files needed to required locations. Make sure the
tasks running user has full access right to the file locations provided.
.LINK
https://bolding.us
#>
[cmdletbinding()]
param (
[Parameter(HelpMessage = "Source Folder", Mandatory = $True)][string[]]$SourceFolder,
[Parameter(HelpMessage = "Target Folders", Mandatory = $True)][string[]]$TargetFolder,
[parameter(HelpMessage = "Recurse the Source Folder")][switch]$Recruse
[parameter(HelpMessage = "Log Location")][string]$Logs = "C:\tmp\SHDMoveFileLog.txt"
)
#Tests to see if local c:\tbc exists, if it doesn't, it will create the path.
if (Test-Path (Split-Path $logs)) { "" >> $logs } else { mkdir (Split-Path $logs) }
#Start with the first source
foreach ($Source in $SourceFolder) {
#Tests to see if the source path exists.
if (Test-Path -Path $Source) {
#Grabs the required files from the first source path. It only grabs files.
#Also checks if there is a recruse flag. If so, recurses accordingly.
if ($Recruse) { $files = Get-childitem -Path $Source -File -Recurse } else { $files = Get-childitem -Path $Source -File }
#Next we sort through the files in question
foreach ($File in $files) {
#Create a test bool.
$success = $false
#Starts the target folder sorting
foreach ($Target in $TargetFolder) {
#Tests to see if target folder exists. If not, logs.
if (Test-Path -Path $target) {
#Enter a try catch to copy the files
try {
#Copys a single file to target folder. Overwrites any other there without confirmation
#No Confiramtion due to the lack of human Interaction.
Copy-Item -Path $file.fullname -Destination $Target -Force -Confirm:$false
#If no error so far, sets the success bool to true
$success = $true
}
catch {
#a failure occured, thus we set the success bool to false
$success = $false
#We log the error. This is the first log that shows up in the system.
#We date it.
#We state it's a catch
#Then we give the reason the try catch gives.
"1;$((Get-Date).tostring());Catch;$($_.Exception)" >> $logs
}
}
else {
#We log the fact that we can't reach the target location
"2;$((Get-Date).tostring());CanNotFind;$Target" >> $logs
}
}
#We test the bool for success.
if ($success -eq $true) {
try {
#if successful we remove the file.
Remove-Item -Path $file.FullName -Force -Confirm:$false
}
catch {
#If we can't remove the file we log the reason why.
"3;$((Get-Date).tostring());Catch;$($_.Exception)" >> $logs
}
}
}
}
else {
#We log the fact we can't reach the source location.
"4;$((Get-Date).tostring());CanNotFind;$Source" >> $logs
}
}
}
Examples
./Invoke-SHDMoveFiles -SourceFolder 'C:\tbc\Tmp\Source Folder\' -TargetFolder 'C:\tbc\tmp\Target Folder\','C:\tbc\tmp\Target Folder 2\'
Moves all files from the source folder 1 to target folders 1 and 2. This is good for a backup of files. What I use this for is a custom software at work. It other products drop to location 1. Then it has a backup folder and the system folder. There we go, good as gold.
./Invoke-SHDMoveFiles -SourceFolder 'C:\tbc\Tmp\Source Folder 1\','C:\tbc\Tmp\Source Folder 2\','C:\tbc\Tmp\Source Folder 3\' -TargetFolder 'C:\tbc\tmp\Target Folder\' -Logs c:\tmp\Combiner.txt
Moves all files from the source folder 1, 2, and 3 to the target folder. It also logs any errors. This is useful when trying to come folders together.
Notes
- This script was designed to be ran as a task. If it doesn’t grab a file the first time around, it will grab it the second time around. It does this by using the try catch. It trys to move a file. if it doesn’t, it logs it and leaves it. We do that because a lot of times these files are being created and have a lock state. It’s best not to move them during that state.
- This script auto logs into the c:\tmp location if you don’t state otherwise when things go wrong.