I need to replace multiple different instances of text in a file using a .bat.
(Note: SQF is just a server config file, Encoding is not an issue)
I have tried:
powershell -Command "(gc Structures.sqf) -replace 'WOOD_WALL', 'CINDERBLOCK_WALL' | Out-File BrickMe.sqf"
powershell -Command "(gc Structures.sqf) -replace 'e614ee17-4467-4d51-a3f2-d4faa61de89e', 'a59f5b71-2b9a-45a2-85bb-ec29a47f78aa' | Out-File BrickMe.sqf"
powershell -Command "(gc Structures.sqf) -replace 'Wood Wall', 'Cinderblock Wall' | Out-File BrickMe.sqf"
But it only performs the last command. Eg. WOOD_WALL remains.
And
sed -e "s/WOOD_WALL/CINDERBLOCK_WALL/" -e "s/Wood Wall/Cinderblock Wall/" <Structures.sqf>BrickMe.sqf
Just creates an empty file called BrickMe.sqf
I have also tried a VBScript to no avail. I would rather keep it able to run on any Windows machine provided the code can handle the file size but I don't know how to replace multiple instances of different text without repeating the whole command and taking a long time.
I have also looked at this http://www.dostips.com/?t=batch.findandreplace
But was unsure of where to put my "WOOD_WALL" instances and my file names.
I have found heaps of results on google for replacing 1 piece of text in multiple files but hardly anything on replacing multiple texts in 1 file.
The Story:
I am running an Arma 3 server and have built a wooden admin base in game that I wish to convert to a cinderblock base. I have done this before but only manually by replacing the Instance Name, Instance_ID and Entity Name. I would like to do it using a batch file if possible and upload it to http://www.exilemod.com to help other admins. The files are usually no larger then 15 Megabytes in size.
I'm pretty awesome with Windows batch files but am new to PowerShell.
It's no wonder that your actions are not successfull.
You always take the original input file, perform actions and save to the same output file this way overwriting the previous action.
For better understanding the PowerShell part broken up:
(gc Structures.sqf) -replace 'WOOD_WALL', 'CINDERBLOCK_WALL' `
-replace 'e614ee17-4467-4d51-a3f2-d4faa61de89e',
'a59f5b71-2b9a-45a2-85bb-ec29a47f78aa' `
-replace 'Wood Wall', 'Cinderblock Wall' |
Out-File BrickMe.sqf
As the -replace operator is RegEx based the 1st and 3rd replace can be joined by:
placing a character class [_ ] underscore or space inside
a capture group ([_ ]) and
using the capture group in the replacement string $1
(gc Structures.sqf) -replace 'WOOD([_ ])WALL', 'CINDERBLOCK$1WALL' `
-replace 'e614ee17-4467-4d51-a3f2-d4faa61de89e',
'a59f5b71-2b9a-45a2-85bb-ec29a47f78aa' |
Out-File BrickMe.sqf
All this wrapped again in a cmd line:
powershell -NoProfile -Command "(gc Structures.sqf) -replace 'WOOD([_ ])WALL', 'CINDERBLOCK$1WALL' -replace 'e614ee17-4467-4d51-a3f2-d4faa61de89e','a59f5b71-2b9a-45a2-85bb-ec29a47f78aa'|Out-File BrickMe.sqf"
I'm running PowerShell v4 and I'm trying to read in a multi-line text file that I want as a single string without line breaks. However, even when I use the -Raw parameter, it is still coming in as an array. It seems like after I put in the -Path the -Raw parameter isn't available anymore because I can't use tab completion for it.
I know there are ways to work around this issue. I'm wondering if anyone has insight into why it isn't working as expected.
Below command works for me:
((Get-Content $file) -join "`n") + "`n" | Set-Content -NoNewline $file
Works for PS v5
Using powershell, I want to take a .bat file and replace all lines in which set is called to set an environment variable and change it to a corresponding setx call. Unfortunately it's not as simple as just doing a search and replace on the file, replacing set for setx, because the syntax is diffferent: set ENVNAME=abc vs setx ENVNAME abc.
Is there a simple way to do this in powershell? To just do the set for setx replacement, I have:
(Get-Content $orig_filename ) | ForEach-Object {$_ -replace "set", "setx"} | Set-Content $new_filename
Any pointers for a powershell novice would be appreciated.
Did some pretty limited testing and I'm not sure what your bat file looks like, but this may work for you.
(Get-Content $orig_filename ) | ForEach-Object {
$_ -replace 'set (.*)\=(.*)','setx $1 $2'
} | Set-Content $new_filename
You could also just chain another -replace to do the work for you. Also made the set > setx replacement a little more less error prone by ensuring you are replacing the word set at the beginning of the string. Since -replace functions as an array operator you do not need the foreach loop.
(Get-Content $orig_filename ) -replace "^set\b", "setx" -replace "="," " | Set-Content $new_filename
I am trying to replicate the functionality of the cat command in Unix.
I would like to avoid solutions where I explicitly read both files into variables, concatenate the variables together, and then write out the concatenated variable.
Simply use the Get-Content and Set-Content cmdlets:
Get-Content inputFile1.txt, inputFile2.txt | Set-Content joinedFile.txt
You can concatenate more than two files with this style, too.
If the source files are named similarly, you can use wildcards:
Get-Content inputFile*.txt | Set-Content joinedFile.txt
Note 1: PowerShell 5 and older versions allowed this to be done more concisely using the aliases cat and sc for Get-Content and Set-Content respectively. However, these aliases are problematic because cat is a system command in *nix systems, and sc is a system command in Windows systems - therefore using them is not recommended, and in fact sc is no longer even defined as of PowerShell Core (v7). The PowerShell team recommends against using aliases in general.
Note 2: Be careful with wildcards - if you try to output to inputFiles.txt (or similar that matches the pattern), PowerShell will get into an infinite loop! (I just tested this.)
Note 3: Outputting to a file with > does not preserve character encoding! This is why using Set-Content is recommended.
Do not use >; it messes up the character encoding. Use:
Get-Content files.* | Set-Content newfile.file
In cmd, you can do this:
copy one.txt+two.txt+three.txt four.txt
In PowerShell this would be:
cmd /c copy one.txt+two.txt+three.txt four.txt
While the PowerShell way would be to use gc, the above will be pretty fast, especially for large files. And it can be used on on non-ASCII files too using the /B switch.
You could use the Add-Content cmdlet. Maybe it is a little faster than the other solutions, because I don't retrieve the content of the first file.
gc .\file2.txt| Add-Content -Path .\file1.txt
To concat files in command prompt it would be
type file1.txt file2.txt file3.txt > files.txt
PowerShell converts the type command to Get-Content, which means you will get an error when using the type command in PowerShell because the Get-Content command requires a comma separating the files. The same command in PowerShell would be
Get-Content file1.txt,file2.txt,file3.txt | Set-Content files.txt
I used:
Get-Content c:\FileToAppend_*.log | Out-File -FilePath C:\DestinationFile.log
-Encoding ASCII -Append
This appended fine. I added the ASCII encoding to remove the nul characters Notepad++ was showing without the explicit encoding.
If you need to order the files by specific parameter (e.g. date time):
gci *.log | sort LastWriteTime | % {$(Get-Content $_)} | Set-Content result.log
You can do something like:
get-content input_file1 > output_file
get-content input_file2 >> output_file
Where > is an alias for "out-file", and >> is an alias for "out-file -append".
Since most of the other replies often get the formatting wrong (due to the piping), the safest thing to do is as follows:
add-content $YourMasterFile -value (get-content $SomeAdditionalFile)
I know you wanted to avoid reading the content of $SomeAdditionalFile into a variable, but in order to save for example your newline formatting i do not think there is proper way to do it without.
A workaround would be to loop through your $SomeAdditionalFile line by line and piping that into your $YourMasterFile. However this is overly resource intensive.
To keep encoding and line endings:
Get-Content files.* -Raw | Set-Content newfile.file -NoNewline
Note: AFAIR, whose parameters aren't supported by old Powershells (<3? <4?)
I think the "powershell way" could be :
set-content destination.log -value (get-content c:\FileToAppend_*.log )
Hi I'm completely new to Powershell so pardon me if this question has a really simple answer.
I would like to use Powershell to look thru a textfile, get all values and prefix and post fix these values with a character.
How can this be done?
Thanks
To add a prefix and suffix to each line of a file (with default command aliases this would be a lot shorter, but full names are clearer):
get-content input-file | `
foreach-object -process { "Prefix" + $_ + "Suffix" } | `
out-file output-file
Add -encoding UTF8 to the out-file to override the default encoding (UTF-16).
To do this in place output-file will need to be a temporary file and then replace the input-file after the processing has completed or read the input file into memory.