This is my attempt at learning PowerShell. No edu background in coding/scripting. Only learned Batch by reading different examples here in StackOverflow and Superuser, trying to adapt found snippets to what is needed, and a lot of trial and error. Please be kind!
There are several strings (without the numbering) that needs to be added to a txt file sequentially and to the top of the file:
- [/This/IsJust.AnExample]
- IsThisTrue=False
- IsThisFalse=
I attempted to "convert" what was found to something that might look usable in a Batchfile:
start "" /wait /min powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "(Get-ChildItem 'D:\Sample Path\%sample_var%\Sample file.txt' -File -recurse | Where{!(Select-String -SimpleMatch '([/This/IsJust.AnExample])|(IsThisTrue=False)|(IsThisFalse=)' -Path $_.fullname -Quiet)} | ForEach{ $Path = $_.FullName '([/This/IsJust.AnExample])|(IsThisTrue=False)|(IsThisFalse=)',(Get-Content $Path) | Set-Content $Path })"
Expectation:
- Look for each string. If it doesn't exist, add it
- The string(s) must only be added if they/it do(es) not exist
Example: If it's entirely missing
[/MoreRandom /Example/In /Here]
MaybeThisIsCorrect=False
MaybeIAmConfused=True
MaybeINeedToLearnTheBasicsOfPowershell=True
MyEnglishIsTerrible=True
Apologetic=True
Expected:
[/This/IsJust.AnExample]
IsThisTrue=False
IsThisFalse=
[/MoreRandom /Example/In /Here]
MaybeThisIsCorrect=False
MaybeIAmConfused=True
MaybeINeedToLearnTheBasicsOfPowershell=True
MyEnglishIsTerrible=True
Apologetic=True
- The string(s) must be always added to the top of the file in the order they were written in and reordered if they were found in other lines
Example:
<newline/blank>
<last string>
<newline/blank>
<string1>
<newline/blank>
<existing content>
Expected:
<string1>
<string2>
<last string>
<newline/blank>
<existing content>
- The top of the page must not have any spaces or blanks
Example:
<newline/blank>
<newline/blank>
<newline/blank>
<string1>
<last string>
<string2>
<newline/blank>
<existing content>
Expected:
<string1>
<string2>
<last string>
<newline/blank>
<existing content>
- The last string added must have a blank after to separate it from the existing content Example:
<last string>
<newline/blank>
<existing content starts here>
- All must be inline, no external files such as .ps1, .bat, .txt, etc.
- It doesn't need an -include since it's only searching in a specific file.
- Must be usable in a batchfile because it's gonna be added to a for loop.
- Always able to handle spaces in file paths
- Must be able to handle encoding with BOM (some snippets added random non-Latin characters)
Result of original attempt:
- It just fails without doing anything to the txt.
Result of attempts after receiving suggestions/info:
start "" /wait /min powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "(Get-ChildItem 'example.txt' -File -recurse -PipelineVariable FilePath | Where{!(Select-String -SimpleMatch '([/This/IsJust.AnExample])|(IsThisTrue=False)|(IsThisFalse=)' -Path $_.fullname -Quiet)} | ForEach{ [string[]]$ToAdd = [string]::Empty; $Out = Get-Content $FilePath -raw; Switch ($Out){{$_ -notmatch [regex]::Escape('[/This/IsJust.AnExample]')}{$ToAdd += '[/This/IsJust.AnExample]'};{$_ -notmatch 'IsThisTrue=False'}{$ToAdd += 'IsThisTrue=False'};{$_ -notmatch 'IsThisFalse='}{$ToAdd += 'IsThisFalse='}};$ToAdd,$Out | Set-Content -Path $FilePath})"- works but it always adds the missing string on the top of the page not in the order they were written in. It also does not add a blank (separator) in between the last string and the first line of the existing content.'([/This/IsJust.AnExample])|(IsThisTrue=False)|(IsThisFalse=)'- Adds a single line instead of checking each string if it exists('[/This/IsJust.AnExample]','IsThisTrue=False','IsThisFalse=')- Adds all strings only if all of them of are missing. If there is a single string already present, it won't add the remaining.
Notes:
- After further digging, the file was found out to be encoded as UTF-16 LE BOM
- The file paths are always with spaces
- Added the missing closing parenthesis causing the snippet to crash
- Changed
-NoP -Ex -By -cto-NoProfile -ExecutionPolicy Bypass -Commandas suggested by @Compo
What is causing it to fail and how to properly do it?
A link to a dummies guide on how to convert PowerShell to Batch would also be nice.
Additionally, would appreciate to know which part can be reused in order to add more strings if needed in the future.
Mmm... If you want that the solution works in a Batch file, why not write it in a Batch file in first place? Besides, IMHO the Batch solution is simpler than the PowerShell one and it runs much faster than the PS one, specially if you want to run it in a loop...
EDIT 2023/10/16: Code modified as requested in comments...
If you want to run this code in a loop you could directly insert it in the loop, or you can convert it into a subroutine (adding a
:labelat beginning and anexit /Bat end) andcall :labelin the loopPS - You said you need this code run in a
forloop, but you don't specify which value will be modified in the loop... If you do so, we could write the complete solutionEDIT 2023/10/17 New code added because there are A LOT of changes!
This question have been modified several times with new specifications each time it is modified. Let's review your examples and descriptions so far:
<existing content>. It does NOT specify that a string could be in the<existing content><existing content>Again, it does NOT specify that a string could be in the<existing content><last string>the result must contain a<newline/blank>and then<existing content starts here>What this "existing content" is? The contents of the input file below the strings (as specified). You never specified that THE EXISTING CONTENT OF THE INPUT FILE COULD INCLUDE A STRING!!! If the "existing content" have a string, then it MUST BE MODIFIED (by removing such a string) when it is passed to the result file. In such a case, it can't be longer called EXISTING CONTENT!!!!! In other words: if you called it "existing content", then you used a term opposite to the desired result (so it is a term that generates confusion, instead of being descriptive)...You have explained A LOT of things, but not the important ones...
You should help us to help you, not hide important information that makes it difficult to help you...
:(I hope the new code below solve you problem (at least, the last one)...
LAST CODE: I give up...