I have to move files from one folder to another every hour.
If there is a copy of a file in the destination folder I want it named FileName_1. In the next hour if the original file is copied again from the source want it named FileName_2. If it still exists then FileName_3, then FileName_4 so on and so forth.
Currently, I can get to FileName_1 only. The issue is that since I change the file name and replace it with a new one it overwrites FileName_1.
Hold up a second. I did my homework here. I have a code block that will sort the files by names, split the name, and add 1 to the file counter but I don't reach this part of the code because the initial check (if the file exists) is always true after the first copy is made.
Any help is appreciated.
Code:
#Sources
$source = "C:\Users\Desktop\TEST\Test_1\*"
$sourceNameChange = "C:\Users\Desktop\TEST\Test_1"
#Destination
$destination = "C:\Users\Desktop\TEST\Test_2"
Function MoveFiles{
Param(
[string]$src,
[string]$dest,
[string]$srcNameChange
)
Get-ChildItem -Force -Recurse $src -ErrorAction Stop -ErrorVariable SearchError | ForEach-Object{
$fileNameSrc = $_.Name
$baseNameSrc = $_.BaseName
# Check for duplicate files
$testPath = Test-Path -Path $dest\$baseNameSrc.*
If( $testPath )
{
$fileCounter = 1
$newName = $_.BaseName "_" $fileCounter $_.Extension
"$srcNameChange\$fileNameSrc" | Rename-Item -NewName $newName
}
$testPathDest = Test-Path -Path $dest\$baseNameSrc_.*
If($testPathDest){
$sort = Get-Item -Path $dest\* -Filter *$baseNameSrc_* | Sort-Object -Property Name -Descending
$destFileName = $sort[1].BaseName
$destFileCounter = $destFileName.Split("_")[1]
$destNewName = $_.BaseName "_" ($destFileCounter 1) $_.Extension
"$srcNameChange\$fileNameSrc" | Rename-Item -NewName $destNewName
}
}
Move-Item -Path $src -Destination $dest -Force
}
MoveFiles -src $source -dest $destination -srcNameChange $sourceNameChange
CodePudding user response:
I added lots of inline comments to help you get through the logic of the function, basically, what your code is missing is a loop that increases the index of the file you're moving until it doesn't exist.
Note, be sure that $destination
is not a folder contained inside $source
or you would end up with unexpected results due to the use of -Recurse
.
function Move-Files {
[cmdletbinding()]
param(
[parameter(Mandatory, ValueFromPipeline)]
[string] $Source,
[parameter(Mandatory)]
[string] $Destination
)
begin {
# if destination doesn't exist, create the folder
if(-not (Test-Path $destination)) {
$null = New-Item -Path $destination -ItemType Directory
}
}
process {
# get all the files in `$source` and iterate over them
Get-ChildItem $source -File -Recurse -Force | ForEach-Object {
# check if a file with the same name exists in `$destination`
$thisFile = Join-Path $destination -ChildPath $_.Name
# if it does exist
if(Test-Path $thisFile) {
$i = 0
# start a loop, using `$i` as index
do {
# increase `$i` on each iteration and get a new name
$newName = $_.BaseName "_" $i $_.Extension
# join the destination path with the new name
$thisFile = Join-Path $destination -ChildPath $newName
# do this while `$thisFile` exists on `$destination`
} while(Test-Path $thisFile)
}
# if we are here we can assume that either the file didn't exist
# on `$destination` OR the `do` loop got us a new name
Move-Item -LiteralPath $_.FullName -Destination $thisFile
}
}
}
$source = 'C:\Users\Desktop\TEST\Test_1'
$destination = 'C:\Users\Desktop\TEST\Test_2'
Move-Files -Source $source -Destination $destination