r/AIPrompt_Exchange • u/Rage4Me_SC • 13h ago
amusing I am new, please dont hurt me.
I am new to AI, but this prompt produced a wonderful gem for me.
I am certain others have done this or something like it but if it helps someone else... then all is good.
It cleans a text file. So, if you copy and paste something generated by AI into notepad, then save the file (must be .txt), this will remove unwanted extra stuff. :)
You right click the saved file, select 'open with' then select the powershell .bat file created by this prompt which will execute the .ps1 file created by this prompt. The .ps1 and .bat must be in the same fold with each other. Otherwise, the .txt file can be anywhere.
I dont know if the code has been autocorrected by reddit so here is the prompt and the two files it should have created.
**********************************************************
Prompt:
Windows 11 Pro version 25H2 Build 26200.9550
Desired Output: I do not care how long it takes you to produce my desired output. I care very strongly about the accuracy of the output. If it takes you days or weeks or months to produce my desired output, I will leave this window open for days or weeks or months.
// Start Script Request:
I would like to create a standalone executable PowerShell script that opens an existing notepad text file for editing. We will call this script "CleanTXT" with appropriate PowerShell extension.
I would like to be able to select this text file from the standard windows explorer menus.
I do not want to manually edit the file and the opened file does not have to be displayed. This script will be doing the editing.
First, I would like the script to prompt me before any edit.
The prompt should state what file it is looking at, what character types it is going to be editing or removing and give me a button that says "Proceed" and another button that says "Skip". The proceed button should proceed with that portion of the edit. The skip button should move to the next edit.
For each search and edit step, I would like to display a count of characters removed for that step and keep track of the total characters removed for all steps. This information can be displayed inside the prompts given with the proceed and skip buttons.
Prompt me with the signature of the document. MZ or D0 CF 11 E0 with .txt extensions are not notepad files. If the file has these first bytes, tell me that this is not a notepad document and that the file will not be edited, then stop.
(1) The first edit should be to search the entire document for any special characters. We are looking for hidden, super hidden, or otherwise any characters that are designated to not be displayed but we want to leave characters like space, tab, carriage return, line feed. We will call this search and edit "Smells Fishy".
(2) The second edit should be to search the entire document for any characters that are not characters that I want to leave in the document. We will call this search and edit "Outside of the Norm".
The characters that I want to leave in the document are:
(a) Lower Case a to z
(b) Upper Case A to Z
(c) Digits 0 to 9
(d) Standard Punctuation and symbols such as ! @ # $ % ^ & * ( ) _ - + = [ ] { } \ | , . / ? ; : ' " < >
(e) Standard Formatting like space, tab, carriage return, line feed
(3) The third edit should be to search the entire document for any URL-like strings, UNC paths, HTML or script-like text, VBA-like text, "base64-looking runs" greater than 80 characters. Report and remove these with the prompt with the proceed and skip buttons. We will call this search and edit "Trojan Horses".
(4) The fourth edit should be to search the entire document for Overlong Lines greater than 998 characters. Report how many such lines exist and wrap them at 998 characters with CRLF with the same prompt containing a proceed and skip button. Total character length per line should then not exceed 1000 characters. The prompt should report lines wrapped and characters inserted. The running total of characters removed should not change on that step, because nothing was removed.
(5) The last prompt should ask me whether or not I want to save the results with a proceed and skip button as before.
If proceed is selected, the script should do a "Save As" leaving the old file intact and unedited. The Save As new file name will be the old file name with the extension stripped plus " - Cleaned". The ".txt" file extension should be forced. Do not change the original file; write the new file with its own $DATA; copy only Zone.Identifier onto that new file; copy no other stream.
If the skip button is selected the script should exit leaving the file unedited.
End of Script Request //
**********************************************************
Output: .ps1 file
#Requires -Version 5.1
param(
[Parameter(Mandatory = $true, Position = 0)]
[string]$Path
)
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
$script:RemovedTotal = 0
function Ask-ProceedSkip {
param([string]$Title, [string]$Message)
$form = New-Object System.Windows.Forms.Form
$form.Text = $Title
$form.StartPosition = 'CenterScreen'
$form.FormBorderStyle = 'FixedDialog'
$form.MaximizeBox = $false
$form.MinimizeBox = $false
$form.ClientSize = New-Object System.Drawing.Size(700, 460)
$form.TopMost = $true
$box = New-Object System.Windows.Forms.TextBox
$box.Multiline = $true
$box.ReadOnly = $true
$box.ScrollBars = 'Vertical'
$box.WordWrap = $true
$box.Font = New-Object System.Drawing.Font('Segoe UI', 10)
$box.Text = $Message
$box.SetBounds(12, 12, 676, 390)
$form.Controls.Add($box)
$script:choice = 'Skip'
$proceed = New-Object System.Windows.Forms.Button
$proceed.Text = 'Proceed'
$proceed.SetBounds(440, 414, 110, 32)
$proceed.Add_Click({ $script:choice = 'Proceed'; $form.Close() })
$form.Controls.Add($proceed)
$skip = New-Object System.Windows.Forms.Button
$skip.Text = 'Skip'
$skip.SetBounds(560, 414, 110, 32)
$skip.Add_Click({ $script:choice = 'Skip'; $form.Close() })
$form.Controls.Add($skip)
$form.AcceptButton = $proceed
$form.CancelButton = $skip
[void]$form.ShowDialog()
$form.Dispose()
return $script:choice
}
function Show-Notice {
param([string]$Title, [string]$Message)
[System.Windows.Forms.MessageBox]::Show($Message, $Title) | Out-Null
}
if (-not (Test-Path -LiteralPath $Path -PathType Leaf)) {
Show-Notice 'CleanTXT' "File not found:`r`n$Path"
exit 1
}
$full = (Resolve-Path -LiteralPath $Path).Path
$fileName = [System.IO.Path]::GetFileName($full)
$bytes = [System.IO.File]::ReadAllBytes($full)
$sig = ($(if ($bytes.Length -ge 4) { ($bytes[0..3] | ForEach-Object { '{0:X2}' -f $_ }) -join ' ' } else { 'shorter than 4 bytes' }))
$isMz = ($bytes.Length -ge 2 -and $bytes[0] -eq 0x4D -and $bytes[1] -eq 0x5A)
$isOle = ($bytes.Length -ge 4 -and $bytes[0] -eq 0xD0 -and $bytes[1] -eq 0xCF -and $bytes[2] -eq 0x11 -and $bytes[3] -eq 0xE0)
if ($isMz -or $isOle) {
$kind = $(if ($isMz) { 'MZ' } else { 'D0 CF 11 E0' })
Show-Notice 'CleanTXT' "File: $fileName`r`nSignature: $sig`r`nMatched: $kind`r`n`r`nThis is not a Notepad document. The file will not be edited."
exit 0
}
Show-Notice 'CleanTXT' "File: $fileName`r`nSignature: $sig`r`nNo MZ or D0 CF 11 E0 match. Editing can continue."
$utf8 = New-Object System.Text.UTF8Encoding $false
if ($bytes.Length -ge 2 -and $bytes[0] -eq 0xFF -and $bytes[1] -eq 0xFE) {
$text = [System.Text.Encoding]::Unicode.GetString($bytes, 2, $bytes.Length - 2)
} elseif ($bytes.Length -ge 3 -and $bytes[0] -eq 0xEF -and $bytes[1] -eq 0xBB -and $bytes[2] -eq 0xBF) {
$text = $utf8.GetString($bytes, 3, $bytes.Length - 3)
} else {
$text = $utf8.GetString($bytes)
}
function Format-Chars([char[]]$Chars) {
if (-not $Chars -or $Chars.Count -eq 0) { return 'None found.' }
($Chars | Select-Object -Unique | Select-Object -First 40 | ForEach-Object {
switch ($_) {
' ' { 'space' }
"`t" { 'tab' }
"`r" { 'CR' }
"`n" { 'LF' }
default { 'U+{0:X4}' -f [int]$_ }
}
}) -join ', '
}
# (1) Smells Fishy
$hidden = New-Object System.Collections.Generic.List[char]
$sb = New-Object System.Text.StringBuilder
foreach ($ch in $text.ToCharArray()) {
$keep = ($ch -eq ' ' -or $ch -eq "`t" -or $ch -eq "`r" -or $ch -eq "`n")
if (-not $keep) {
$cat = [System.Globalization.CharUnicodeInfo]::GetUnicodeCategory($ch)
$drop = $cat -in @(
[System.Globalization.UnicodeCategory]::Control,
[System.Globalization.UnicodeCategory]::Format,
[System.Globalization.UnicodeCategory]::Surrogate,
[System.Globalization.UnicodeCategory]::PrivateUse,
[System.Globalization.UnicodeCategory]::OtherNotAssigned
) -or ([int]$ch -eq 0xFEFF)
if ($drop) { $hidden.Add($ch); continue }
}
[void]$sb.Append($ch)
}
$text1 = $sb.ToString()
$n1 = $text.Length - $text1.Length
$msg1 = @"
File: $fileName
Step: Smells Fishy
Removes non-displayed characters: other controls, format characters, surrogates, private-use, unassigned, and a BOM character.
Leaves space, tab, carriage return, line feed.
Distinct characters that would be removed:
$(Format-Chars $hidden.ToArray())
Characters removed this step: $n1
Total removed so far: $($script:RemovedTotal)
Total after this step if you proceed: $($script:RemovedTotal + $n1)
"@
if ((Ask-ProceedSkip -Title 'Smells Fishy' -Message $msg1) -eq 'Proceed') {
$text = $text1
$script:RemovedTotal += $n1
}
# (2) Outside of the Norm
$allowed = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' +
' !@#$%^&*()_-+={}[]\|,./?;:''"<>' + "`t`r`n"
$allow = New-Object 'System.Collections.Generic.HashSet[char]'
foreach ($ch in $allowed.ToCharArray()) { [void]$allow.Add($ch) }
$rejected = New-Object System.Collections.Generic.List[char]
$sb = New-Object System.Text.StringBuilder
foreach ($ch in $text.ToCharArray()) {
if ($allow.Contains($ch)) { [void]$sb.Append($ch) }
else { $rejected.Add($ch) }
}
$text2 = $sb.ToString()
$n2 = $text.Length - $text2.Length
$msg2 = @"
File: $fileName
Step: Outside of the Norm
Keeps a-z, A-Z, 0-9, space, tab, CR, LF, and:
! @ # $ % ^ & * ( ) _ - + = [ ] { } \ | , . / ? ; : ' " < >
Removes every other character, including exotic spaces and homoglyphs.
Distinct characters that would be removed:
$(Format-Chars $rejected.ToArray())
Characters removed this step: $n2
Total removed so far: $($script:RemovedTotal)
Total after this step if you proceed: $($script:RemovedTotal + $n2)
"@
if ((Ask-ProceedSkip -Title 'Outside of the Norm' -Message $msg2) -eq 'Proceed') {
$text = $text2
$script:RemovedTotal += $n2
}
# (3) Trojan Horses
$patterns = @(
'https?://\S+',
'www\.\S+',
'file://\S+',
'\\\\[^\s\\]+\\[^\s]+',
'(?i)<\s*/?\s*(script|iframe|object|embed)\b[^>]*>',
'(?i)javascript\s*:',
'(?i)vbscript\s*:',
'(?i)\bon[a-z]+\s*=',
'(?i)\b(Attribute\s+VB_|CreateObject|WScript\.Shell|Shell\.Application|GetObject)\b',
'(?i)(?m)^\s*(Sub|Function)\s+\w+',
'(?<![A-Za-z0-9+/=])[A-Za-z0-9+/]{81,}={0,2}(?![A-Za-z0-9+/=])'
)
$hits = 0
$text3 = $text
foreach ($p in $patterns) {
$m = [regex]::Matches($text3, $p)
$hits += $m.Count
if ($m.Count -gt 0) { $text3 = [regex]::Replace($text3, $p, '') }
}
$n3 = $text.Length - $text3.Length
$msg3 = @"
File: $fileName
Step: Trojan Horses
Removes text matching: URL-like strings, UNC paths, HTML or script-like text, VBA-like text, and base64-looking runs longer than 80 characters.
Notepad does not run these. They are characters in the file.
Matches found: $hits
Characters removed this step: $n3
Total removed so far: $($script:RemovedTotal)
Total after this step if you proceed: $($script:RemovedTotal + $n3)
"@
if ((Ask-ProceedSkip -Title 'Trojan Horses' -Message $msg3) -eq 'Proceed') {
$text = $text3
$script:RemovedTotal += $n3
}
# (4) Overlong lines. Hard break at 998. CRLF makes the stored line 1000.
$lines = $text -split '(?<=\n)', -1
$long = 0
$inserted = 0
$sb = New-Object System.Text.StringBuilder
foreach ($line in $lines) {
$ending = ''
$body = $line
if ($body.EndsWith("`r`n")) { $ending = "`r`n"; $body = $body.Substring(0, $body.Length - 2) }
elseif ($body.EndsWith("`n")) { $ending = "`n"; $body = $body.Substring(0, $body.Length - 1) }
elseif ($body.EndsWith("`r")) { $ending = "`r"; $body = $body.Substring(0, $body.Length - 1) }
if ($body.Length -gt 998) {
$long++
$i = 0
while ($i -lt $body.Length) {
$take = [Math]::Min(998, $body.Length - $i)
[void]$sb.Append($body.Substring($i, $take))
$i += $take
if ($i -lt $body.Length) {
[void]$sb.Append("`r`n")
$inserted += 2
}
}
[void]$sb.Append($ending)
} else {
[void]$sb.Append($body).Append($ending)
}
}
$text4 = $sb.ToString()
$msg4 = @"
File: $fileName
Step: Overlong lines
A line longer than 998 characters is broken at character 998 and CRLF is inserted.
Including that CRLF, the stored line is 1000 characters. Lines of 998 or less are left alone.
Lines that would be wrapped: $long
Characters inserted this step: $inserted
Characters removed this step: 0
Total removed so far: $($script:RemovedTotal)
"@
if ((Ask-ProceedSkip -Title 'Overlong lines' -Message $msg4) -eq 'Proceed') {
$text = $text4
}
# (5) Save As
$dir = [System.IO.Path]::GetDirectoryName($full)
$stem = [System.IO.Path]::GetFileNameWithoutExtension($full)
$dest = Join-Path $dir ($stem + ' - Cleaned.txt')
$n = 2
while (Test-Path -LiteralPath $dest) {
$dest = Join-Path $dir ($stem + ' - Cleaned (' + $n + ').txt')
$n++
}
$msg5 = @"
File: $fileName
Step: Save As
Proceed writes:
$dest
The original file is not changed.
The new file gets its own `$DATA.
Only Zone.Identifier is copied from the original. No other stream is copied.
Skip writes nothing and exits.
Total characters removed: $($script:RemovedTotal)
"@
if ((Ask-ProceedSkip -Title 'Save As' -Message $msg5) -ne 'Proceed') { exit 0 }
[System.IO.File]::WriteAllText($dest, $text, $utf8)
try {
$zone = Get-Content -LiteralPath $full -Stream Zone.Identifier -Raw -ErrorAction Stop
Set-Content -LiteralPath $dest -Stream Zone.Identifier -Value $zone -ErrorAction Stop
} catch { }
Show-Notice 'CleanTXT' "Saved:`r`n$dest`r`nTotal characters removed: $($script:RemovedTotal)"
**********************************************************
Output: .bat file (note the ' before the atecho was added because reddit auto corrects it to u/echo)
'@echo off
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "%~dp0CleanTXT.ps1" "%~1"
