Search code examples
stringpowershellpathpowershell-5.0new-item

New-item "Illegal Characters in path" when I use a Variable that contains a here string


foreach ($Target in $TargetUSBs)
{
$LogPath= @"
$SourceUSB\$(((Get-CimInstance -ClassName Win32_volume)|where {$_.DriveType -eq "2" -and $_.DriveLetter -eq $Target}).SerialNumber)_
$(((Get-CimInstance -ClassName Win32_OperatingSystem).LocalDateTime).Year)$(((Get-CimInstance -ClassName Win32_OperatingSystem).LocalDateTime).Month)
$(((Get-CimInstance -ClassName Win32_OperatingSystem).LocalDateTime).Day)_$(((Get-CimInstance -ClassName Win32_OperatingSystem).LocalDateTime).Hour)
$(((Get-CimInstance -ClassName Win32_OperatingSystem).LocalDateTime).Minute)$(((Get-CimInstance -ClassName Win32_OperatingSystem).LocalDateTime).Second).txt
"@

    $LogPath = $LogPath.Replace("`n","").Trim()
    New-item -Path "$LogPath"
}

The Irony is when I copy and paste the contents of my variable and manually create a new-item -path and paste said contents it works but when I use the variable it does not... Brief summary of my goal I am taking a USB labelled ORIGINAL and obtaining the S/N of every USB plugged in at the time and creating separate log files for each with the title consisting of SERIALNUMBER_DATE_TIME.txt and these files are created in ORIGINAL USB

$LogPath contains for example the following: E:\Mattel\1949721369_2018912_93427.txt Yet when I use the Variable in New-item it indicates "Illegal characters in Path"

FYI $LogPath is a System.String not an object $TargetUSBs is filled with all USB drives plugged into the system

this method of using a variable for a path usually works fine for me only difference is the here-string I used this time around does this cause my problem? I hope not because I really don't want to fill that variable all on one line. New-Item's helpfiles shows <String[]> for -path parameter does this mean I have to use a string array? and if so how do I convert this to make this work?


Solution

  • Your problem is that Windows uses CRLF line endings (Unix only LF), so you still have CR chars in your path.

    To fix this just use:

    .Replace("`r`n","")
    

    However you can easily simplify your code so you do not require the messy here-string or replace/trim...

    By using a single Get-Date call you can format it to your desired output. This means you can just build the Path as a simple string and involves much less code:

    foreach ($Target in $TargetUSBs)
    {
        $SerialNumber = Get-CimInstance -ClassName Win32_volume | where {$_.DriveType -eq "2" -and $_.DriveLetter -eq $Target} | Select-Object -ExpandProperty SerialNumber
        $DateTime = Get-Date -Format "yyyyMd_Hms"
    
        New-item -Path "$SourceUSB\$SerialNumber_$DateTime.txt"
    }