Powershell Function Copy Files - powershell

I´m facing to an issue that i can´t figure it out, how can i solve.
Basically i´ve an function that copy files from one directory to another directory, and rename it, if they already exists.
In the mean while, if any file with case sensitive name, it don´t copy it at all.
example:
TEXT.xml
text.xml
It just copy one of them. i need to copy both files.
Now, is the Rename-Item or the Copy-Item, that can´t deal with this case sensitive? Any idea how can i solve this?
Thanks for any help
My code:
Function Copy-File {
[CmdletBinding()]
param(
[Parameter(Mandatory = $true, Position = 0)]
[string]$Origin,
[Parameter(Mandatory = $true, Position = 1)]
[string]$Destination
)
# check if a file with that name already exists within the destination
$fileName = Join-Path $Destination ([System.IO.Path]::GetFileName($Origin))
if (Test-Path $fileName -PathType Leaf){
$baseName = [System.IO.Path]::GetFileNameWithoutExtension($Origin)
$extension = [System.IO.Path]::GetExtension($Origin) # this includes the dot
$allFiles = Get-ChildItem $Destination | Where-Object {$_.PSIsContainer -eq $false} | Foreach-Object {$_.Name}
$newName = $baseName + $extension
$count = 1
while ($allFiles -contains $newName) {
$newName = [string]::Format("{0}({1}){2}", $baseName, $count.ToString(), $extension)
$count++
}
# rename the file already in the destination folder
# Write-Verbose -Message "Renaming file '$fileName' to '$newName'"
Rename-Item $fileName -NewName $newName
}
#Write-Verbose -Message "Moving file '$Origin' to folder '$Destination'"
Copy-Item $Origin $Destination
}

All of what you are after here is just doing this...
(always use validation testing for all destructive commands/code --- (Delete/Rename/Modify/Update/Move))
Clear-Host
$SourceFiles = 'D:\Temp\Source'
$Destination = 'D:\Temp\Destination'
$Counter = 0
Get-ChildItem -Path $SourceFiles |
ForEach{
Try
{
If(Test-Path -Path $Destination\$PSItem)
{
$Counter++
Write-Warning -Message "$($PSItem.Name) already exits. Renaming destination file."
Rename-Item -Path $Destination\$PSItem -NewName "$($PSItem.Basename)_$Counter$($PSitem.Extension)" -WhatIf
# Copy-Item -Path $PSItem.FullName -Destination $Destination -WhatIf
}
Else
{
Write-Verbose -Message "$($PSItem.Name) does not exist. Copying file." -Verbose
Copy-Item -Path $PSItem.FullName -Destination $Destination -WhatIf
}
}
Catch {$PSItem.Exception.Message}
}
# Results
<#
VERBOSE: 5 Free Software You'll Wish You Knew Earlier! 2019 - YouTube.url does not exist. Copying file.
What if: Performing the operation "Copy File" on target "Item: D:\Temp\Source\5 Free Software You'll Wish You Knew Earlier! 2019 - YouTube.url Destination: D:\Temp\Destination\5 Free Software You'll Wish You Knew Earlier! 2019 - YouTube.url".
WARNING: audiolengthCLEAN.csv already exits. Renaming destination file.
What if: Performing the operation "Rename File" on target "Item: D:\Temp\Destination\audiolengthCLEAN.csv Destination: D:\Temp\Destination\audiolengthCLEAN_2.csv".
...
#>
Update as per your function question.
Function Sync-FileArchive
{
[CmdletBinding(SupportsShouldProcess)]
[Alias('sfa')]
Param
(
[Parameter(Mandatory = $true, Position = 0)]
[string]$SourceFiles,
[Parameter(Mandatory = $true, Position = 1)]
[string]$Destination
)
$Counter = 0
Get-ChildItem -Path $SourceFiles |
ForEach{
Try
{
If(Test-Path -Path $Destination\$PSItem)
{
$Counter++
Write-Warning -Message "$($PSItem.Name) already exits. Renaming destination file."
Rename-Item -Path $Destination\$PSItem -NewName "$($PSItem.Basename)_$Counter$($PSitem.Extension)" -WhatIf
}
Else
{
Write-Verbose -Message "$($PSItem.Name) does not exist. Copying file." -Verbose
Copy-Item -Path $PSItem.FullName -Destination $Destination
}
}
Catch {$PSItem.Exception.Message}
}
}
# Example1 - Remove the -WhatIf to fully execute.
Sync-FileArchive -SourceFiles 'D:\Temp\Source' -Destination 'D:\Temp\Destination' -WhatIf
# Example2
sfa 'D:\Temp\Source' 'D:\Temp\Destination' -WhatIf

Related

PowerShell Copy All Files in Folders and Sub=Folders Not older than 300 minutes

I am trying to copy all files in folders and sub-folders not older than 300 minutes, but the code I got working only copies the files in the main folder, it doesn't copy the files in subfolders.
At the destination I don't want to maintain the folder structure of the original files, I just want to put all the origin files into a single specific destination folder.
This is the code I have:
Powershell -NoL -NoP -C "&{$ts=New-TimeSpan -M 300;"^
"Get-ChildItem "C:\Origin" -Filter '*.dat'|?{"^
"$_.LastWriteTime -gt ((Get-Date)-$ts)}|"^
%%{Copy-Item $_.FullName 'C:\Destination'}}"
Could someone help me out please?
Thanks in advance.
Here's a modified script for you you can save as "Copy-Unique.ps1" you can run from a batch file.
function Copy-Unique {
# Copies files to a destination. If a file with the same name already exists in the destination,
# the function will create a unique filename by appending '(x)' after the name, but before the extension.
# The 'x' is a numeric sequence value.
[CmdletBinding(SupportsShouldProcess)] # add support for -WhatIf switch
Param(
[Parameter(Mandatory = $true, ValueFromPipeline = $true, Position = 0)]
[Alias("Path")]
[ValidateScript({Test-Path -Path $_ -PathType Container})]
[string]$SourceFolder,
[Parameter(Mandatory = $true, Position = 1)]
[string]$DestinationFolder,
[Parameter(Mandatory = $false)]
[int]$NewerThanMinutes = -1,
[Parameter(Mandatory = $false)]
[string]$Filter = '*',
[switch]$Recurse
)
# create the destination path if it does not exist
if (!(Test-Path -Path $DestinationFolder -PathType Container)) {
Write-Verbose "Creating folder '$DestinationFolder'"
$null = New-Item -Path $DestinationFolder -ItemType 'Directory' -Force
}
# get a list of file FullNames in this source folder
$sourceFiles = #(Get-ChildItem -Path $SourceFolder -Filter $Filter -File -Recurse:$Recurse)
# if you want only files not older than x minutes, apply an extra filter
if ($NewerThanMinutes -gt 0) {
$sourceFiles = #($sourceFiles | Where-Object { $_.LastWriteTime -gt (Get-Date).AddMinutes(-$NewerThanMinutes) })
}
foreach ($file in $sourceFiles) {
# get an array of all filenames (names only) of the files with a similar name already present in the destination folder
$destFiles = #((Get-ChildItem $DestinationFolder -File -Filter "$($file.BaseName)*$($file.Extension)").Name)
# for PowerShell version < 3.0 use this
# $destFiles = #(Get-ChildItem $DestinationFolder -Filter "$baseName*$extension" | Where-Object { !($_.PSIsContainer) } | Select-Object -ExpandProperty Name)
# construct the new filename
$newName = $file.Name
$count = 1
while ($destFiles -contains $newName) {
$newName = "{0}({1}){2}" -f $file.BaseName, $count++, $file.Extension
}
# use Join-Path to create a FullName for the file
$newFile = Join-Path -Path $DestinationFolder -ChildPath $newName
Write-Verbose "Copying '$($file.FullName)' as '$newFile'"
$file | Copy-Item -Destination $newFile -Force
}
}
# you can change the folder paths, file pattern to filter etc. here
$destFolder = Join-Path -Path 'C:\Destination' -ChildPath ('{0:yyyy-MM-dd_HH-mm}' -f (Get-Date))
Copy-Unique -SourceFolder "C:\Origin" -DestinationFolder $destFolder -Filter '*.dat' -Recurse -NewerThanMinutes 300
Changed the code to now take a datetime object to compare against rather than an amount of minutes. This perhaps makes the code easier to understand, but certainly more flexible.
function Copy-Unique {
# Copies files to a destination. If a file with the same name already exists in the destination,
# the function will create a unique filename by appending '(x)' after the name, but before the extension.
# The 'x' is a numeric sequence value.
[CmdletBinding(SupportsShouldProcess)] # add support for -WhatIf switch
Param(
[Parameter(Mandatory = $true, ValueFromPipeline = $true, Position = 0)]
[Alias("Path")]
[ValidateScript({Test-Path -Path $_ -PathType Container})]
[string]$SourceFolder,
[Parameter(Mandatory = $true, Position = 1)]
[string]$DestinationFolder,
[string]$Filter = '*',
[datetime]$NewerThan = [datetime]::MinValue,
[switch]$Recurse
)
# create the destination path if it does not exist
if (!(Test-Path -Path $DestinationFolder -PathType Container)) {
Write-Verbose "Creating folder '$DestinationFolder'"
$null = New-Item -Path $DestinationFolder -ItemType 'Directory' -Force
}
# get a list of file FullNames in this source folder
$sourceFiles = #(Get-ChildItem -Path $SourceFolder -Filter $Filter -File -Recurse:$Recurse)
# if you want only files newer than a certain date, apply an extra filter
if ($NewerThan -gt [datetime]::MinValue) {
$sourceFiles = #($sourceFiles | Where-Object { $_.LastWriteTime -gt $NewerThan })
}
foreach ($file in $sourceFiles) {
# get an array of all filenames (names only) of the files with a similar name already present in the destination folder
$destFiles = #((Get-ChildItem $DestinationFolder -File -Filter "$($file.BaseName)*$($file.Extension)").Name)
# for PowerShell version < 3.0 use this
# $destFiles = #(Get-ChildItem $DestinationFolder -Filter "$baseName*$extension" | Where-Object { !($_.PSIsContainer) } | Select-Object -ExpandProperty Name)
# construct the new filename
$newName = $file.Name
$count = 1
while ($destFiles -contains $newName) {
$newName = "{0}({1}){2}" -f $file.BaseName, $count++, $file.Extension
}
# use Join-Path to create a FullName for the file
$newFile = Join-Path -Path $DestinationFolder -ChildPath $newName
Write-Verbose "Copying '$($file.FullName)' as '$newFile'"
$file | Copy-Item -Destination $newFile -Force
}
}
# you can change the folder paths, file pattern to filter etc. here
$destFolder = Join-Path -Path 'D:\Destination' -ChildPath ('{0:yyyy-MM-dd_HH-mm}' -f (Get-Date))
Copy-Unique -SourceFolder "C:\Origin" -DestinationFolder $destFolder -Filter '*.dat' -Recurse -NewerThan (Get-Date).AddMinutes(-300)
When you have saved the above code to let's say 'C:\Scripts\Copy-Unique.ps1' you can then call it from a batch file like:
Powershell.exe -NoLogo -NoProfile -File "C:\Scripts\Copy-Unique.ps1"

Recursively copying files matching on pattern

I've put together a script that recursively copies from one directory to another, skipping files with a certain pattern in the filename:
function Copy-RevitFiles ([string]$source, [string]$destination, [boolean]$recurse) {
$pattern = '\.\d\d\d\d\.[RVT]'
if ($recurse) {$files = Get-ChildItem $source -Recurse}
else {$files = Get-ChildItem $source}
$files | ForEach-Object {
if ((Select-String -InputObject $_.Name -pattern $pattern -AllMatches -quiet) -eq $null) {
#Write-Host $_.Name
#Write-Host $_.Fullname
#Write-Host "$($destination)\$($_.FullName.TrimStart($source))"
Copy-Item $_.FullName -Destination "$($destination)\$($_.FullName.TrimStart($source))" #add on full name of item, less $source start end of file path
#Write-Host "----------"
}
}
}
It works well, for the most part. The problem I have though is that it creates an additional subfolder inside each folder with files in it. For example:
If input the source as a directory with this structure:
Source
-file1.rvt
-file1.0225.rvt (will not copy as it matches the pattern)
-file1.0226.rvt (will not copy as it matches the pattern)
-folder1
|-file2.rvt
|-file2.0121.rvt (will not copy as it matches the pattern)
|-file2.0122.rvt (will not copy as it matches the pattern)
-folder2
I am expecting the following structure to be created in the destination folder:
Destination
-file1.rvt
-folder1
|-file2.rvt
-folder2
But instead, I am getting:
Destination
-file1.rvt
-folder1
|-file2.rvt
|-folder1 (extra folder not in source)
-folder2
Any idea where I am going wrong?
It's the way you construct the destination and also how you handle the returned value for the Select-STring cmdlet with option -Quiet.
Using the Quiet switch will have the cmdlet return a Boolean value ($true or $false), but you are testing for equality to $null.
If I use the Join-Path cmdlet (along with some other adjustments to your function) like this:
function Copy-RevitFiles {
[CmdletBinding()]
Param(
[string]$source,
[string]$destination,
[string]$pattern,
[switch]$recurse
)
# test if the destination folder exists
if (!(Test-Path -Path $destination -PathType Container)) {
New-Item -ItemType Directory -Path $destination -Force | Out-Null
}
$files = Get-ChildItem $source -Recurse:$recurse
$files | ForEach-Object {
if (!(Select-String -InputObject $_.Name -Pattern $pattern -AllMatches -Quiet)) {
#Write-Host $_.Name
#Write-Host $_.Fullname
$target = Join-Path -Path $destination -ChildPath $_.Fullname.TrimStart($source)
#Write-Host "Copying '$_.Fullname' to '$target'"
$_ | Copy-Item -Destination $target
#Write-Host "----------"
}
}
}
and use it according to your Source example:
Copy-RevitFiles -source "D:\Source" -destination "D:\Destination" -pattern '\.\d\d\d\d\.[RVT]' -recurse
It will result in:
Destination
| file1.rvt
|
+---folder1
| file2.rvt
|
\---folder2

Copy-Item 'preview' of output

Quick question regarding the PowerShell Copy-Item command. I was wondering if you have a directory structure and wanted to overwrite another directory structure is there a way to run the Copy-Item command in a 'preview' mode. It would output what files its overwriting from directory a to directory b but not actually perform the Copy-Item command.
Any help or advice appreciated.
Thanks.
Interesting question!
Here is my attempt of doing it all in Powershell, so not needing RoboCopy.
function Copy-Preview {
[CmdletBinding(DefaultParameterSetName = 'ByPath')]
param(
[Parameter(ValueFromPipeline = $true, Mandatory = $true, ParameterSetName = 'ByPath', Position = 0)]
[ValidateScript({ Test-Path $_ })]
[string]$Path,
[Parameter(ValueFromPipeline = $true, Mandatory = $true, ParameterSetName = 'ByLiteralPath', Position = 0)]
[ValidateScript({ Test-Path $_ })]
[string]$LiteralPath,
[Parameter(ValueFromPipeline = $true, Mandatory = $true, Position = 1)]
[string]$Destination,
[string]$Filter = $null,
[string]$Include = $null,
[string]$Exclude = $null,
[switch]$Recurse,
[switch]$Force
)
if ($PSCmdlet.ParameterSetName -eq 'ByLiteralPath') { $Path = $LiteralPath }
# determine if $Path and $Destination hold a file or a directory
$srcIsFolder = (Test-Path $Path -PathType Container -ErrorAction SilentlyContinue)
# cannot use Test-Path here because then the path has to exist.
# assume if it has an extension the path is a file, otherwise a directory
# NOTE:
# This is certainly not fullproof, so to avoid problems, always make sure
# the destination ends with a backslash if a directory is intended.
$destIsFolder = (-not ([System.IO.Path]::HasExtension($Destination)))
if ($destIsFolder -and !(Test-Path $Destination -PathType Container)) {
Write-Host "Destination path does not exist yet. All files from '$Path' will be copied fresh" -ForegroundColor Green
return
}
elseif ($srcIsFolder -and (!$destIsFolder)) {
# should not happen: source is a directory, while the destination is a file..
Write-Error "When parameter Path points to a directory, the Destination cannot be a file.."
return
}
$count = 0
if ($srcIsFolder -and $destIsFolder) {
# Both the source and the destinations are folders
# make sure both paths are qualified for .Replace() further down
if (-not $Path.EndsWith("\")) { $Path += "\" }
if (-not $Destination.EndsWith("\")) { $Destination += "\" }
$splat = #{
Filter = $Filter
Include = $Include
Exclude = $Exclude
Recurse = $Recurse
Force = $Force
}
# add either Path or LiteralPath to the parameters as they are mutually exclusive
if ($PSCmdlet.ParameterSetName -eq 'ByPath') { $splat.Path = $Path }
else { $splat.LiteralPath = $LiteralPath }
$srcFiles = Get-ChildItem #splat | Select-Object -ExpandProperty FullName
# reuse the splat parameters hash for the destination, but change the Path
if ($splat.LiteralPath) {($splat.Remove("LiteralPath"))}
$splat.Path = $Destination
$destFiles = Get-ChildItem #splat | Select-Object -ExpandProperty FullName
foreach ($srcItem in $srcFiles) {
$destItem = $srcItem.Replace($Path, $Destination)
if ($destFiles -contains $destItem) {
Write-Host "'$destItem' would be overwritten"
$count++
}
}
}
elseif (!$srcIsFolder) {
# the source is a file
if (!$destIsFolder) {
# the destination is also a file
if (Test-Path $Destination -PathType Leaf) {
Write-Host "'$Destination' would be overwritten"
$count++
}
}
else {
# source is file, destination is a directory
$destItem = Join-Path $Destination (Split-Path $Path -Leaf)
if (Test-Path $destItem -PathType Leaf) {
Write-Host "'$destItem' would be overwritten"
$count++
}
}
}
$msg = "$count item{0} would be overwritten by Copy-Item" -f $(if ($count -ne 1) { 's' })
$dash = "-" * ($msg.Length)
Write-Host "$dash`r`n$msg" -ForegroundColor Green
}
tl;dr:
Copy-Item -WhatIf will not give you the level of detail you're looking for - see below.
Use robocopy.exe -l instead (Windows only), as Ansgar Wiechers recommends, because it individually lists what files would be copied, including dynamically omitting those already present in the target dir (with the same size and last-modified time stamp, by default).
Generally, robocopy is faster and more fully featured than Copy-Item, and it avoids a notable pitfall of the latter.
Get-Help about_CommonParameters documents the -WhatIf common parameter supported by many (but not all) cmdlets, whose purpose is to preview an operation without actually performing it.
However, this feature is implemented in an abstract fashion, and often doesn't provide information as detailed as one would hope.
Case in point: while Copy-Item does support -WhatIf, it probably won't give you the level of detail you're looking for, because if the source item is a directory, only a single line such as the following is output:
What if: Performing the operation "Copy Directory" on target "Item: sourceDir Destination: destDir".
Note that you'll see the same line whether or not your Copy-Item call includes the -Recurse switch.
Even if you ensure existence of the target directory manually and append /* to the source directory path in order to see individual filenames, you'd only see them at the child level, not further down the subtree, and you'd never get the dynamic information that robocopy -l provides with respect to what files actually need replacement.
You can use the -whatif parameter.
Copy-item -path myfile.txt -destination myfoldertoCopyTo\ -whatif

Copy file based a specified folder based on file name. Create folder if it doesn't exist

I'm trying to copy files to a specific folder based on a file name.
For example:
Current Folder - C:\Stuff\Old Files\
The File- 206.Little Rock.map.pdf
Destination Folder - D:\Cleanup\206\Repository
So basically the leading number on the file (206) is part of the subfolder. The "\Repository" would stay constant. Only the leading number would change.
If the file was 207.Little Rock.map.pdf then the destination folder would be
D:\Cleanup\207\Repository
I started with a code I got from here but I'm not sure how to account for the change in number and how to make it create a folder if the folder doesn't exist. So 206\Repository would probably already exist, but I would need the script to create the folder if it doesn't.
$SourceFolder = "C:\Stuff\Old Files\"
$targetFolder = "D:\Cleanup\"
$numFiles = (Get-ChildItem -Path $SourceFolder -Filter *.pdf).Count
$i=0
clear-host;
Write-Host 'This script will copy ' $numFiles ' files from ' $SourceFolder ' to ' $targetFolder
Read-host -prompt 'Press enter to start copying the files'
Get-ChildItem -Path $SourceFolder -Filter *.PDF | %{
[System.IO.FileInfo]$destination = (Join-Path -Path $targetFolder -ChildPath $Name.Repository(".*","\"))
if(!(Test-Path -Path $destination.Directory )){
New-item -Path $destination.Directory.FullName -ItemType Directory
}
[int]$percent = $i / $numFiles * 100
copy-item -Path $_.FullName -Destination $Destination.FullName
Write-Progress -Activity "Copying ... ($percent %)" -status $_ -PercentComplete $percent -verbose
$i++
}
Write-Host 'Total number of files read from directory '$SourceFolder ' is ' $numFiles
Write-Host 'Total number of files that was copied to '$targetFolder ' is ' $i
Read-host -prompt "Press enter to complete..."
clear-host;
This should do mostly what you need. You might have to tweak the destination path a bit, but that should be fairly straight forward to figure out. I Highly recommend that use a '-' as the delimiter for your file prefix as opposed to a '.' as this will prevent accidentally moving EVERY FILE in a directory if you happen to execute it in the wrong place.
Also, when you write a script, do create functions to do individual units of work, and then call those functions at the end. It's much easier to modify, and debug that way.
<#
.SYNOPSIS
Moves files from source to destination based on FileName
Creates destination folder if it does not exist.
.DESCIPTION
The script expects files with a prefix defined by a hyphen '-' i.e. 200-<filename>.<ext>.
There is no filename validation in this script; it will *probably* skip files without a prefix.
A folder based on the prefix will be created in the destination.
If your file is name string-cheese.txt then it will be moved to $DestinationIn\string\string-cheese.txt
.PARAMETER SourceIn
Source Path (folder) where your files exist.
.PARAMETER DestinationIn
Target Path (folder) where you want your files to go.
.EXAMPLE
& .\CleanUp-Files.ps1 -SourceIn "C:\Users\User\Documents\Files\" -DestinationIn "C:\Users\User\Documents\Backup\" -Verbose
.NOTES
Author: RepeatDaily
Email: RepeatedDaily#gmail.com
This script is provided as is, and will probably work as intended. Good Luck!
https://stackoverflow.com/questions/50662140/copy-file-based-a-specified-folder-based-on-file-name-create-folder-if-it-doesn
#>
[CmdletBinding()]
param (
[string]$SourceIn,
[string]$DestinationIn
)
function Set-DestinationPath {
param (
[string]$FileName,
[string]$Target
)
[string]$NewParentFolderName = $FileName.SubString(0,$FileName.IndexOf('-'))
[string]$DestinationPath = Join-Path -Path $Target -ChildPath $NewParentFolderName
return $DestinationPath
}
function Create-DestinationPath {
[CmdletBinding()]
param (
[string]$Target
)
if (-not(Test-Path -Path $Target)) {
Try {
New-Item -ItemType Directory -Path $Target | Write-Verbose
}
catch {
Write-Error $Error[0];
}
}
else {
Write-Verbose "$Target exists"
}
}
function Move-MyFiles {
[CmdletBinding()]
param (
[string]$Source,
[string]$Destination
)
[array]$FileList = Get-ChildItem $Source -File | Select-Object -ExpandProperty 'Name'
foreach ($file in $FileList) {
[string]$DestinationPath = Set-DestinationPath -FileName $file -Target $Destination
Create-DestinationPath -Target $DestinationPath
try {
Move-Item -Path (Join-Path -Path $Source -ChildPath $file) -Destination $DestinationPath | Write-Verbose
}
catch {
Write-Warning $Error[0]
}
}
}
Move-MyFiles -Source $SourceIn -Destination $DestinationIn
Here is something you might try. The number for the directory is grabbed from a regex match, "(\d+)\..*.pdf". When you are confident that the correct file copies will be made, remove the -WhatIf from the Copy-Item cmdlet.
I did not try to address the Write-Progress capability. Also, this will only copy .pdf files that begin with digits followed by a FULL STOP (period) character.
I do not fully understand the need for all of the Write-Host and Read-Host usage. It is not very PowerShell. pwshic
$SourceFolder = 'C:/src/t/copymaps'
$targetFolder = 'C:/src/t/copymaps/base'
$i = 0
$numFiles = (
Get-ChildItem -File -Path $SourceFolder -Filter "*.pdf" |
Where-Object -FilterScript { $_.Name -match "(\d+)\..*.pdf" } |
Measure-Object).Count
clear-host;
Write-Host 'This script will copy ' $numFiles ' files from ' $SourceFolder ' to ' $targetFolder
Read-host -prompt 'Press enter to start copying the files'
Get-ChildItem -File -Path $SourceFolder -Filter "*.pdf" |
Where-Object -FilterScript { $_.Name -match "(\d+)\..*.pdf" } |
ForEach-Object {
$NumberDir = Join-Path -Path $targetFolder -ChildPath $Matches[1]
$NumberDir = Join-Path -Path $NumberDir -ChildPath 'Repository'
if (-not (Test-Path $NumberDir)) {
New-Item -ItemType Directory -Path $NumberDir
}
Copy-Item -Path $_.FullName -Destination $NumberDir -Whatif
$i++
}
Write-Host 'Total number of files read from directory '$SourceFolder ' is ' $numFiles
Write-Host 'Total number of files that was copied to '$targetFolder ' is ' $i
Read-host -prompt "Press enter to complete..."
clear-host;

Using Powershell I want to Forcefully Copy Folder/files Without Erasing Extra Files in Existing Destination Folder:

I am using Powershell and am trying to forcefully copy folder/files without erasing any extra files in existing destination folders. I am stuck trying to get a working command.
Below is my code, any suggestions on how to fix this?
Copy-Item -Force -Recurse –Verbose $releaseDirectory -Destination $sitePath
you need to be sure that
$realeseDirectory
is something like
c:\releasedirectory\*
Copy-item never delete extra files or folders in destination, but with -force it will owerwrite if file already exists
Your question isn't very clear. So, you might have to tweak the function below a bit. By the way, if you are attempting to deploy a web site, copying a directory isn't the best way.
function Copy-Directory
{
param (
[parameter(Mandatory = $true)] [string] $source,
[parameter(Mandatory = $true)] [string] $destination
)
try
{
Get-ChildItem -Path $source -Recurse -Force |
Where-Object { $_.psIsContainer } |
ForEach-Object { $_.FullName -replace [regex]::Escape($source), $destination } |
ForEach-Object { $null = New-Item -ItemType Container -Path $_ }
Get-ChildItem -Path $source -Recurse -Force |
Where-Object { -not $_.psIsContainer } |
Copy-Item -Force -Destination { $_.FullName -replace [regex]::Escape($source), $destination }
}
catch
{
Write-Error "$($MyInvocation.InvocationName): $_"
}
}
$releaseDirectory = $BuildFilePath + $ProjectName + "\" + $ProjectName + "\bin\" + $compileMode + "_PublishedWebsites\" + $ProjectName
$sitePath = "\\$strSvr\c$\Shared\WebSites"
Copy-Directory $releaseDirectory $sitePath