Trying to debug a file-transfer operation. Basically, I want PowerShell to merge two folders ($sourceDir and $targetDir), and rename any files in $sourceDir that already exist in $targetDir. It sort of does that, but instead of preserving the directory structure of the source folder, it’s moving all the files from the source directory into the root of the target.
I know that adding the -Container flag on a standard Move-Item will force it to reconstruct the directory structure, but I’ve tried adding that here and I get errors.
This is what I have:
$sourceDir = "E:\Folder1"
$targetDir = "W:\Folder1"
Get-ChildItem -Path $sourceDir -Recurse | ForEach-Object {
$num=1
$nextName = Join-Path -Path $targetDir -ChildPath $_.name
while(Test-Path -Path $nextName)
{
$nextName = Join-Path $targetDir ($_.BaseName + "_$num" + $_.Extension)
$num+=1
}
$_ | Move-Item -Destination $nextName -Verbose
}
I’ve inserted write-host lines into it right above the Move-Item command and I can confirm it’s targeting the root directory of the destination instead of maintaining the directory structure from the source. I’ve tried changing Get-ChildItem -Path to -LiteralPath, I’ve tried adding | % { $_.FullName } | after the GCI, but no matter what I do the result I get is something different than what I’m looking for.
>Solution :
All files are being relocated to the root of the target directory because the script only uses the file name to create the destination path. You must include the subdirectory path in the destination path in order to maintain the directory structure of the source folder.
The script has been changed, and it should still maintain the directory structure, as follows:
$sourceDir = "E:\Folder1"
$targetDir = "W:\Folder1"
Get-ChildItem -Path $sourceDir -Recurse | ForEach-Object {
$relativePath = $_.FullName.Substring($sourceDir.Length)
$nextName = Join-Path -Path $targetDir -ChildPath $relativePath
$num = 1
while(Test-Path -Path $nextName)
{
$nextName = Join-Path $targetDir ($relativePath + "_$num" + $_.Extension)
$num += 1
}
$_ | Move-Item -Destination $nextName -Verbose
}
By deducting the length of the source directory path from the complete path of the file, the script first determines the relative path of each file. The target path is then built using the relative path.