I am constructing incremental directory structures, and for some reason Join-Path
is showing 2 dirs. When I later join that with a file I'm sending to copy-item, it causes an error, as shown below. I have shown in the comment for the $to_loc_finalDT1
line, where I first see these two dirs:
Copy-Item : Cannot find path '\\T2\DisasterBackup\Loc_2019-03-08\Privileges\Privileges_HH_Bak.csv \\T2\DisasterBackup\Loc_2019-03-08\Privileges\Privileges_HH_Bak.csv' because it does not exist
So this is the pertinent powershell script:
$T2 = "\\T2\DisasterBackup\Loc"
$toLocParentDT2 = CreateDatedFolder $parentDirBaseNameDT2
$to_loc_finalDT2 = Join-Path -Path $toLocParentDT2 -ChildPath "Privileges"
#create sub-folder location
if(-Not (Test-Path $to_loc_finalDT2 ))
{
write-output " Creating folder $to_loc_finalDT2 because it does not exist "
New-Item -ItemType directory -Path $to_loc_finalDT2 -force
}
#second dir save files to
$parentDirBaseNameDT1 = "\\T1\DisasterBackup\Loc"
$toLocParentDT1 = CreateDatedFolder $parentDirBaseNameDT1
$to_loc_finalDT1 = Join-Path -Path $toLocParentDT1 -ChildPath "Privileges" #shows 2 dirs here in debugger: \\T2\DisasterBackup\Loc_2019-03-08\Privileges \\T2\DisasterBackup\Loc_2019-03-08\Privileges
#create sub-folder location
if(-Not (Test-Path $to_loc_finalDT1 ))
{
write-output " Creating folder $to_loc_finalDT1 because it does not exist "
New-Item -ItemType directory -Path $to_loc_finalDT1 -force
}
I'm not sure how to get Join-Path
to just have the one dir, as it should. Right now, I think it's being treated as an array, which is not correct.
I tried searching for related issues, but didn't see anything similar.
Update
Here's the code for CreateDatedFolder:
#create dated folder to put backup files in
function CreateDatedFolder([string]$name){
$datedDir = ""
$datedDir = "$name" + "_" + "$((Get-Date).ToString('yyyy-MM-dd'))"
New-Item -ItemType Directory -Path $datedDir -force
return $datedDir
}
The output for that looks fine when it's returned. It appends the date onto the \T2\DisasterBackup\Loc, but the debugger only shows one dir there, not an array or 2 dirs that are separate strings.
As T-Me correctly inferred before you posted the CreateDatedFolder
source, the problem is that the function inadvertently outputs 2 objects, and Join-Path
accepts an array of parent paths to each join with the child path.
Specifically, it is the New-Item
call that accidentally creates an additional output object, just before your return $datedDir
call.
New-Item
outputs a [System.IO.DirectoryInfo]
instance representing the newly created directory and, due to PowerShell's implicit output behavior, that instance becomes part of what the function outputs too - any command or expression inside a script / function that returns a value that isn't captured or redirected becomes part of the output.
To prevent that, suppress the output:
$null = New-Item -ItemType Directory -Path $datedDir -force
Other ways to suppress output are discussed in this answer, which also discusses the design rationale for PowerShell's implicit output behavior.
Note that you never need return
in PowerShell in order to output a result - but you may need it for flow control, to exit a function prematurely:
return $datedDir
is syntactic sugar for:
$datedDir # Implicitly output the value of $datedDir.
# While you could also use `Write-Output $datedDir`,
# that is rarely needed and actually slows things down.
return # return from the function - flow control only
For more information about PowerShell's implicit output behavior, see this answer.