Using PowerShell to replace string that contains + in the string - powershell

I am trying to use PowerShell do a simple find and replace. Essentially, I used to have some support files in a directory with the same name of a "master" file. All but one of those support files are no longer necessary. The "master" file has a text reference to the path of the other file. What I want to do is modify this path in the "master" file to remove the deleted directory.
For example, let's say I have the file C:\Temp\this+that.txt I used to have C:\Temp\this+that\this+that.dat that has now been moved to C:\Temp\this+that.dat
C:\Temp\this+that.txt has a line like this:
/temp/this+that/this+that.dat
I would like this line to become:
/temp/this+that.dat
I have lots of these files that a batch file is moving. Everything is working fine using the powershell command below for all file names that do NOT contain a plus + sign. For those files, the call below does not work.
powershell -Command "(gc '!CURRENT_FILE!') -replace '/!BASE_NAME!/', '/' | Set-Content '!CURRENT_FILE!'"
For the example above, CURRENT_FILE would be C:\Temp\this+that.txt and BASE_NAME would be this+that
Can anyone help me with why this isn't working for file names that contain a plus + sign?

#ma_il is exactly right. The '+' character is a special character in RegEx, so you will need to escape it.
powershell -Command "(gc '!CURRENT_FILE!') -replace [regex]::escape('/!BASE_NAME!/'), '/' | Set-Content '!CURRENT_FILE!'"

Related

Including a script does not work when path has special characters

I am trying to include a script inside another which is in the same folder, using the dot syntax:
. '.\BaseScript.ps1'
The path to the scripts has a folder with square brackets in the name. Even though I am using relative paths, the path error still occurs.
Moving it to some other path without special characters in the name works fine.
How can such a case be catered while using relative paths?
Unfortunately, PowerShell treats the operands to the . dot-sourcing and & call operators (which includes implicit invocation[1] ) as wildcard expressions, which causes problems with paths that contain [, which is a wildcard metacharacter.
The solution is to escape the [ as `[; e.g., to dot-source a script whose path is ./test[1]/script.ps1:
# Note: '/' and '\' can be used interchangeably in PowerShell.
. ./test`[1]/script.ps1
Important: If the path is relative, it must start with ./ or .\ (see below for full paths).
Note: [ is a wildcard metacharacter, because you can use it to express character ranges ([a-z]) or sets ([56]); while ] is clearly also needed, it is sufficient to escape [.
This unfortunate requirement, which also affects other contexts, is the subject of GitHub issue #4726.
Alternatively - and bizarrely - as Theo's helpful answer shows, the need for this escaping goes away if you use a full path.
# Dot-source 'script.ps1` from the same location as the running
# script ($PSScriptRoot).
# (Use $PWD to refer to the *currrent* dir.)
# Because this results in a *full* path, there is no need to escape, strangely.
. $PSScriptRoot/script.ps1
[1] &, which can invoke any command and runs commands written in PowerShell code in a child scope, isn't strictly needed for invocation; e.g. & ./path/to/script.ps1 and ./path/to/script.ps1 are equivalent; however, & is required if the path is quoted and/or contains variable references - see this answer.
The way around this seems to be using a complete path to the second script:
. (Join-Path -Path $PSScriptRoot -ChildPath 'SecondScript.ps1')
#Theo has a useful workaround, but the cause is that [] must be escaped in paths.
$path = 'C:\path\`[to`]\script.ps1'

How can we use "ls" command for appending file list from FTP to local file?

I'm using the command ls *Pattern*Date* Files.txt to get a list of files from FTP to my local text file.
I'm now required to get multiple patterned files (The Date and Pattern may come in different order). So when I try to add another line ls *Date*Pattern* Files.txt, this clears the FCCfiles.txt and I'm not able to get the first set of files.
Is there any command that can append the list of files rather than creating new files list?
You cannot append the listing to a file with ftp.
But you can merge multiple listings in PowerShell. I assume that you run ftp from PowerShell, based on your use of powershell tag.
In ftp script do:
ls *Pattern*Date* files1.txt
ls *Date*Pattern* files2.txt
And then in PowerShell do:
Get-Content files1.txt,files2.txt | Set-Content files.txt
(based on How do I concatenate two text files in PowerShell?)

Rename and overwrite files using wildcard in Windows

I am working on a script for auto deployment, where I need to replace my files with the same filenames.
For example, I have the following files in my current directory
deployment.properties
wrapper.conf
config.properties
Later, I will generate another set of files like this
deployment.properties.tokenized
wrapper.conf.tokenized
config.properties.tokenized
Lastly, I want to replace the existing config files (in the first code block) using the *.tokenized version and remove the tokenized files.
In Linux, the following can do the job. But I don't know how to do in Windows
for f in *tokenized;
do mv "$f" "`echo $f | sed s/tokenized//`";
done
I tried to use powershell's move-item, rename-item but still cannot figure out the right way to do it. Could somebody help? bat / powershell scripts are both welcomed. Using loop is also okay. Thank you.
It is almost the same code but in cmd / batch files we have access to the elements of the file name.
From command line
for %a in (*.tokenized) do move /y "%a" "%~na"
Or, for a batch file (you need to escape the for replaceable parameter)
for %%a in (*.tokenized) do move /y "%%a" "%%~na"
As the extension of the file (the text after the last dot) is .tokenized, when you request just the name (without extension) of the file being referenced (%%~na) you get the original file name.
This PowerShell script should do the job:
Get-ChildItem *.tokenized | % {
move $_.Name ([System.IO.Path]::GetFileNameWithoutExtension($_.Name)) -Force
}

Beyond Compare - via command Line : Spaces in FilePath

I am trying to run beyond compare via command line.
The command I am using is :
BCompare.exe #"My Config File.txt" "File 1.xml" "File 2.xml"
But this is not working because of spaces in the file Names.
Beyond Compare shows a "file not found" error (as it is looking only for the part of fileName before spaces)
If I compare files without any space in file name, it works.
Since you're running a script but haven't shown that, I suspect you aren't quoting the arguments there properly. The quotes on the command line are going to be stripped as part of the command line processing, so if your script is:
file-report layout:side-by-side %1 %2 output-to:printer
It should actually be
file-report layout:side-by-side "%1" "%2" output-to:printer
Without the extra quotes the variables would be expanded like:
file-report layout:side-by-side File 1.xml File 2.xml output-to:printer

How to pass a variable as an argument to a command with quotes in powershell

My powershell script takes the following parameter:
Param($BackedUpFilePath)
The value that is getting passed into my script is:
"\123.123.123.123\Backups\Website.7z"
I have another variable which is the location I want to extract the file:
$WebsiteDeploymentFolder = "C:\example"
I am trying to extract the archive with the following command:
`7z x $BackedUpFilePath -o$WebsiteDeploymentFolder -aoa
I keep getting the following error:
Error:
cannot find archive
The following works but I need $BackedUpFilePath to be dynamic:
`7z x '\123.123.123.123\Backups\Website.7z' -o$WebsiteDeploymentFolder -aoa
I think I need to pass $BackedUpFilePath to 7z with quotes but they seem to get stripped out no matter what I try. I am in quote hell.
Thanks.
EDIT: It turns out the problem was I was passing in "'\123.123.123.123\Backups\Website.7z'". (extra single quotes)
The easiest way to work with external command line applications in PowerShell (in my opinion) is to use aliases. For example, the following works fine for me.
Set-Alias Szip C:\Utilities\7zip\7za.exe
$Archive = 'C:\Temp\New Folder\archive.7z'
$Filename = 'C:\Temp\New Folder\file.txt'
SZip a $Archive $Filename
PowerShell takes care of delimiting the parameters correctly.