Test-Path - Illegal characters in path when using a variable - powershell

I m fairly new to PowerShell and I apologize in advance if this is a dumb question.
I am trying to construct a new destination/filename where I take the old filename and increment its prefix with +1
$destination = Split-Path -Path 'C:\Users\tom\Desktop\test\0_InstalledPrograms.log'
$file = split-path "C:\Users\tom\Desktop\test\0_InstalledPrograms.log" -Leaf
$array = $file -split '_'
$prefix = $array[0] + 1
$suffix = $array[1]
$newFile = $prefix + '_' + $suffix
$newFile = Out-String -InputObject $newFile
$destination = $destination + '\' + $newFile
Test-Path $destination
Test-Path : Illegal characters in path.
At C:\Users\tom\Desktop\incrementFileName.ps1:18 char:1
+ Test-Path $destination
+ ~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (C:\Users\lgranc...dPrograms.log
:String) [Test-Path], ArgumentException
+ FullyQualifiedErrorId : ItemExistsArgumentError,Microsoft.PowerShell.Commands.TestPathCommand
False

This statement:
$newFile = Out-String -InputObject $newFile
adds a new line (CR+LF) to the string, and is completely unnecessary ($newFile is already a string).
Remove that line and it'll work :)

You can do it easily as follows:
$file = "C:\Users\tom\Desktop\test\0_InstalledPrograms.log"
$splittedName = (Split-Path $file -leaf).split('_')
$newFileName = [string]([int]$splittedName[0] + 1) +'_'+ $splittedName[1]
Move-Item -Path $file -Destination (Join-Path (Split-path $file) -ChildPath $newFileName)

Related

Positional parameter cannot be found error in powershell

I am trying to append the date to a file name in my Powershell script but keep getting the following error (my code is below the error). Any help/direction would be greatly appreciated. Thank you.
Set-Content : A positional parameter cannot be found that accepts
argument '$null'.
At P:\CoverageVerifier\CombineTextFiles.ps1:8 char:50
+ ... thTrailer | Set-Content "${path}\\" + ${$dateStr} + "_CoverageVerifi ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Set-Content], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.SetContentCommand
Here is my powershell code:
$path = "\\xx\\apps\\CoverageVerifier\\"
$pathHeader = "\\xx\\apps\\CoverageVerifier\\Header.txt"
$pathData = "\\xx\\apps\\CoverageVerifier\\Data.txt"
$pathTrailer = "\\xx\\apps\\CoverageVerifier\\Trailer.txt"
$date = Get-Date
$dateStr = $date.ToString("yyyyMMdd")
#Write-Output $dateStr
Get-Content $pathHeader,$pathData,$pathTrailer | Set-Content "${path}\\cvgver." + ${dateStr} + ".0101"
The first positional parameter of the Set-Content cmdlet is the -Path parameter.
Because of the way you define the paths for the files, it is bound to have problems with that.
As I understand, these are UNC paths, so try this instead:
# for LOCAL paths
# Set the driveletter to the actual drive you are using. For demo I'm using 'X:\'
# $path = 'X:\apps\CoverageVerifier'
# for UNC paths
# change 'servername' to your actual servers name
$path = '\\servername\apps\CoverageVerifier'
$pathHeader = Join-Path -Path $path -ChildPath 'Header.txt'
$pathData = Join-Path -Path $path -ChildPath 'Data.txt'
$pathTrailer = Join-Path -Path $path -ChildPath 'Trailer.txt'
$dateStr = (Get-Date).ToString("yyyyMMdd")
$outFile = Join-Path -Path $path -ChildPath ($dateStr + "_TestVerifier.txt")
Get-Content $pathHeader, $pathData, $pathTrailer | Set-Content $outFile
As you can see, I'm using the Join-Path cmdlet a lot to make sure my file paths get concatenated correctly.
Why don't you use the format operator and Join-Path?
Edit even with only one format
$path = "\\xx\apps\CoverageVerifier"
$pathHeader = Join-Path $path "Header.txt"
$pathData = Join-Path $path "Data.txt"
$pathTrailer = Join-Path $path "Trailer.txt"
Get-Content $pathHeader,$pathData,$pathTrailer |
Set-Content (Join-Path $path ("{0:yyyyMMdd}_TestVerifier.txt" -f (Get-Date))
you use set-content to modify the content of a file, not the filename:
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/set-content?view=powershell-6

Copy files renaming if already exists PowerShell

This script works to rename files while copying them if they are duplicates. I need to rename the current destination file first then copy the source file as is. Any ideas?
function Copy-FilesWithVersioning{
Param(
[string]$source,
[string]$destination
)
Get-ChildItem -Path $source -File
ForEach-Object {
$destinationFile = Join-Path $destination $file.Name
if ($f = Get-Item $destinationFile -EA 0) {
# loop for number goes here
$i = 1
$newname = $f.Name -replace $f.BaseName, "$($f.BaseName)_$I")
Rename-Item $destinationFile $newName
}
Copy-Item $_ $destination
}
}
Copy-FilesWithVersioning c:\scripts\Source c:\scripts\DestinationA
Errors:
At line:10 char:53
+ if($f = Get-Item $destinationFile -EA 0){
+ ~
Missing closing '}' in statement block or type definition.
At line:8 char:23
+ ForEach-Object{
+ ~
Missing closing '}' in statement block or type definition.
At line:2 char:34
+ function Copy-FilesWithVersioning{
+ ~
Missing closing '}' in statement block or type definition.
At line:13 char:77
+ ... $newname = $f.Name -replace $f.BaseName, "$($f.BaseName)_$I")
+ ~
Unexpected token ')' in expression or statement.
At line:15 char:13
+ }
+ ~
Unexpected token '}' in expression or statement.
At line:17 char:9
+ }
+ ~
Unexpected token '}' in expression or statement.
At line:18 char:1
+ }
+ ~
Unexpected token '}' in expression or statement.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : MissingEndCurlyBrace
The errors you're seeing are caused by the spurious closing parenthesis in this line:
$newname = $f.Name -replace $f.BaseName, "$($f.BaseName)_$I")
Remove the parenthesis from the end of the line and these errors will disappear.
There are several other mistakes in your code, though, so even with that fixed the code still won't work.
You're missing a pipe between the Get-ChildItem and ForEach-Object. It's required for passing the output of one cmdlet to the other.
Get-ChildItem -Path $source -File |
ForEach-Object {
...
}
The variable $file is undefined. In a PowerShell pipeline you want to work with the "current object" variable ($_). Change this line
$destinationFile = Join-Path $destination $file.Name
into
$destinationFile = Join-Path $destination $_.Name
$_ in the statement
Copy-Item $_ $destination
is expanded to just the name of the file, not the full path. Change that into
Copy-Item $_.FullName $destination
Better yet, move the Copy-Item statement after the ForEach-Object, so you don't need to explicitly specify the source in the first place (the cmdlet reads input from the pipeline):
Get-ChildItem ... | ForEach-Object {
...
$_ # need this line to pass the current object back into the pipeline
} | Copy-Item -Destination $destination
Note that you must output the current object back to the pipeline and specify the destination as a named parameter (-Destination $destination) for the latter to work.
Your check for the presence of a file in the destination folder is a little awkward. Use Test-Path instead. You can construct the new filename from the current object.
if (Test-Path -LiteralPath $destinationFile) {
$i = 1
Rename-Item $destinationFile ($_.BaseName + "_$i" + $_.Extension)
}
Try code from this link: https://www.pdq.com/blog/copy-individual-files-and-rename-duplicates/:
$SourceFile = "C:\Temp\File.txt"
$DestinationFile = "C:\Temp\NonexistentDirectory\File.txt"
If (Test-Path $DestinationFile) {
$i = 0
While (Test-Path $DestinationFile) {
$i += 1
$DestinationFile = "C:\Temp\NonexistentDirectory\File$i.txt"
}
} Else {
New-Item -ItemType File -Path $DestinationFile -Force
}
Copy-Item -Path $SourceFile -Destination $DestinationFile -Force

Powershell rename using variable

Hi am not able to rename a file using the below code. Please help me on this
$date = Get-Date -format "yyyyMMdd"
$path='D:\Users\user\Desktop\Working\'
$fn = $path+'xxx_'+$date+'.txt'
$tn = $path+'yyy'+$date+'.dat'
Rename-Item -Path $fn -NewName $tn
Am getting the below error.
Rename-Item : Cannot process argument because the value of argument "path" is not valid. Change the value of the
"path" argument and run the operation again.
At line:1 char:1
+ Rename-Item -Path $fn -NewName $tn
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Rename-Item], PSArgumentException
+ FullyQualifiedErrorId : Argument,Microsoft.PowerShell.Commands.RenameItemCommand
I'd use Join-Path and Test-Path
$date = Get-Date -format "yyyyMMdd"
$path='D:\Users\user\Desktop\Working\'
$fn = Join-Path $path ("xxx_{0}.txt" -f $date)
$tn = Join-Path $path ("yyy_{0}.txt" -f $date)
If ((Test-Path $fn) -and !(Test-Path $tn)){
Rename-Item -Path $fn -NewName $tn
} else {
"{0} exists is {1}, `n{2} not exists is {3}" -f $fn,(Test-Path $fn),$tn,(!(Test-Path $tn))
}
There is no output on a successful rename, on error the output is like:
D:\Users\user\Desktop\Working\xxx_20180606.txt exists is False,
D:\Users\user\Desktop\Working\yyy_20180606.txt not exists is False

Move-Item to correct Destination

The Script:
Creates a list of folders based on the filenames in the scripts root directory, each folder breaks down the name by "Year/Month/Day"
Moves each file to the designated folder
Error Message:
CategoryInfo : ObjectNotFound:
(S:\Data\TECHNOL...59_20180108.txt:String)
[Move-Item], ItemNotFoundException FullyQualifiedErrorId :
PathNotFound,Microsoft.PowerShell.Commands.MoveItemCommand
My Issue
The files will not move to the correct endpath
#Create Directory
Set-StrictMode -Version 2
$rootPath = split-path -parent $MyInvocation.MyCommand.Definition
cd $rootPath
$FileNameArray = Get-ChildItem -Filter "*.txt"
$FileNameArray = $FileNameArray -replace "....$"
$FileNameArray = $FileNameArray -replace "^59_"
Foreach($f in $FileNameArray)
{
$Year = $f -replace "^\d{0}|\d{4}$" #"....$"
$Month = $f -replace "^\d{4}|\d{2}$"
$Month = $Month | sort -Unique
$Day = $f -replace "^\d{6}|\d{0}$"
#Loop 2a
Foreach($m1 in $Month){
#Loop 2a-a
Foreach($d1 in $Day){
Move-Item -Path ($rootPath + '\59_' + $file + '.txt')
-Destination ($rootPath + '\' + $Year + '\' + $m1 + '\' + $d1)
}
}
}
Apologies for the spaghetti code & simple question, I am new to both Computer Science and PowerShell.
The following script has two security features:
The MD command has a trailing -confirm you have to answer
The Move-Item has a -WhatIf which shows what would be done without the Parameter
If the script works OK, remove them both.
## Q:\Test\2018\05\03\SO_50158185.ps1
Set-StrictMode -Version 2
$rootPath = Split-Path -Parent $MyInvocation.MyCommand.Definition
cd $rootPath
Get-ChildItem "59_20[0-9][0-9][0-1][0-9][0-3][0-9].txt" |
Where-Object {$_.BaseName -Match '59_(?<year>\d{4})(?<Month>\d{2})(?<Day>\d{2})'}|
ForEach-Object {
$DestDir = Join-Path $rootPath ("{0}\{1}\{2}" -f $Matches.Year,$Matches.Month,$Matches.Day)
If (!(Test-Path $DestDir)) {MD $DestDir -Confirm| Out-Null}
$_ | Move-Item -Destination $DestDir -WhatIf
}
Figured it out guys! Just needed to change $file to $f. Thanks for all the help.

Add double quotes to variable to escape space

I am running a script which has $FileName variable containing the absolute path with spaces. Due to the space within the directory name and file name, the script fails to executes without finding the actual path. All I need is to add $FilePath within double quotes. How should I append double quotes in the beginning and end of a string?
For example
"X:\Movies\File One\File One.txt"
Script:
$FilePath = Join-Path $Path $($Dir + "\" + $File + “.txt”)
$FilePath
Current OutPut:
X:\Movies\File One\File One.txt
In addition to the backtick escape character (`), you can use the -f format operator:
$FilePath = Join-Path $Dir -ChildPath "$File.txt"
$FilePathWithQuotes = '"{0}"' -f $FilePath
This will ensure that $FilePath is expanded before being placed in the string
$FilePath = Join-Path $Path $($Dir + "\" + $File + “.txt”)
"`"$FilePath`""
...would output...
"X:\Movies\File One\File One.txt"
This is an example of variable expansion in strings.
Of course, if the path you want to quote could contain " quotes itself, for example in a future "powershell for linux", you'd need to escape the " in a context specific way.
Any one of these should work:
$FilePath1 = """" + (Join-Path $Path $($Dir + "\" + $File + ".txt")) + """"
$FilePath2 = "`"" + (Join-Path $Path $($Dir + "\" + $File + ".txt")) + "`""
$FilePath3 = '"{0}"' -f (Join-Path $Path $($Dir + "\" + $File + ".txt"))
$FilePath4 = '"' + (Join-Path $Path $($Dir + "\" + $File + ".txt")) + '"'
$FilePath5 = [char]34 + (Join-Path $Path $($Dir + "\" + $File + ".txt")) + [char]34
fastest solution (but a bit ugly) to add quotes around any string:
$dir = "c:\temp"
$file = "myfile"
$filepath = [string]::Join("", """", $dir,"\", $file, ".txt", """")