How To Remove Substring Using Batch File - powershell

I have several thousand files with similar, but different formats, ie:
[Block 1] Thisfile.txt
[Block 1] Thisfile1.txt
[Block 1] Thisfile2.txt
[Backup001] Thatfile1.doc
[Backup001] Thatfile2.doc
[Backup001] Thatfile3.doc
[Explode] Thisplace.xls
[Explode] Thisplace1.xls
[Explode] Thisplace2.xls
I want to remove the "[text] " and keep everything else the same. Since that text varies I can't do a strict number of characters ie
set var=%1
#echo %var:~-7%
I tried to dabble with powershell commandline and tried:
dir *.xls | Rename-Item -NewName {$_.Name -replace '[Explode\s\'}
But was given the following error:
Rename-Item : The input to the script block for parameter 'NewName' failed. Invalid regular expression pattern: [Explode\s\.
At line:1 char:33
+ Dir *.xls | Rename-Item -NewName <<<< {$_.Name -replace '[Explode]\s\'}
+ CategoryInfo : InvalidArgument: (C:\1\[Explode... Thisfile1.xls:PSObject) [Rename-Item], ParameterBindingException
+ FullyQualifiedErrorId : ScriptBlockArgumentInvocationFailed,Microsoft.PowerShell.Commands.RenameItemCommand
I've searched StackExchange, and the 'batch-rename' tag, and found (and tried) several similar things that I thought I could tweak, but no luck.
Here's the latest based on another StachExchange answer:
for %%F in (*.xls) do (
SET string=%%F
SET modified=!string:Explode=1!
echo !modified!
)
I was just trying to get ANY replace to work... No luck.

Your PowerShell was fairly solid, the only issue is that the square braces are reserved characters and have to be escaped with a preceding backslash. The RegEx that should work for you should be:
-replace '\[.*?\]\s*'
You can see the detailed explanation of that at this link:
https://regex101.com/r/yM6sQ9/1
Edit: Sorry, just got into work and saw your messages. I tried that regex with a test file and was able to rename it without issues. Test file created:
C:\Temp\[glarb]ThisIsATest.tst
I then ran the following line in PowerShell:
Get-ChildItem C:\Temp\*.tst | Rename-Item -NewName {$_.Name -replace "\[.*\]\s*"}
After which I looked and was left with the file:
C:\Temp\ThisIsATest.tst
I'm not sure why your code didn't work, perhaps it is a bug in your version of PowerShell. The regex and command do work in PS v4 running in Win8.1.

Using pure batch:
#echo off
for /f "delims=" %%F in (
'dir /b /a-d [*]*'
) do for /f "tokens=1* delims=]" %%A in (
"%%F"
) do for /f "tokens=*" %%C in ("%%B") do ren "%%F" "%%C"
Using my JREN.BAT regular expression renaming utility, a pure script utility (hybrid JScript/batch) that runs natively on any Windows machine from XP onward:
call jren "^\[.*?] *" "" /fm "[*]*"
You can drop the CALL if you use the command directly from the command line.

My RegEx-Foo is not very strong (it's on the to-do list), but you should be able to do this with a sub string.
dir *.xls | Rename-Item -NewName { ($_.Name.Substring($_.Name.IndexOf(']') + 1)).Trim() }
Looking a little closer at what actually changed, we're returning a sub string of $_.Name which is from the index after the first ']' character and then also trims the output, dealing with any extra white spaces (namely spaces).
This has the obvious limitation of not working for files that are in the form of:
this[should]notBeEdited.xls

Related

Comments in a long-line PowerShell code in a Batch script

I have a large batch script to which I need to add some Powershell code for some regex capture which I am unable to do in batch. I was hoping to have this code integrated in my batch script using the method outlined in Link, but when adding comments I get a missing } error. I've simplified my code just to be able to replicate the issue.
This, without a comment, works:
#echo OFF
setlocal enabledelayedexpansion enableextensions
set "var=variable"
PowerShell ^
foreach ($file in Get-ChildItem -File -Include *.* -Recurse) ^
{ ^
Write-Host $file; ^
Write-Host $env:var; ^
}
%End PowerShell%
echo Test
pause > nul
This, with a comment, does not work:
#echo OFF
setlocal enabledelayedexpansion enableextensions
set "var=variable"
PowerShell ^
foreach ($file in Get-ChildItem -File -Include *.* -Recurse) ^
{ ^
#Comment ^
Write-Host $file; ^
Write-Host $env:var; ^
}
%End PowerShell%
echo Test
pause > nul
I have tried escaping the # in a few different ways, but no matter what I do, I get the error message
Missing closing '}' in statement block or type definition.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : MissingEndCurlyBrace
The only difference is the comment. Does anyone know how to get around this? (using this long-line method that is). If it's not at all possible I guess I will go for base64 encoding
What works for me if when I do the comment line in between <# and #> as if it were a comment block.
Then of course for cmd you need to escape the < and > characters with a ^:
^<# Comment #^> ^
P.S. Don't forget that using Get-ChildItem without a -Path or -LiteralPath, the cmdlet will use PowerShell's current working folder ($pwd), which is most probably not the same as the current working path cmd uses..
This an hybrid code Batch and Powershell exmaple is just to show you how to put a multiline comment block with powershell and how to execute Batch section and powershell section :
<# : Batch Script Section
#rem # The previous line does nothing in Batch, but begins a multiline comment block in PowerShell. This allows a single script to be executed by both interpreters.
#echo off
Title Wifi Passwords Recovery by Hackoo 2022 & Mode 70,3
setlocal
cd "%~dp0"
Color 0B & echo(
Echo( Please Wait a while ... Getting SSID and Wifi Keys ...
Powershell -executionpolicy bypass -Command "Invoke-Expression $([System.IO.File]::ReadAllText('%~f0'))"
EndLocal
goto:eof
#>
# Powershell Script Section begin here...
# here we execute our powershell commands...
$Var=netsh wlan show profiles|SLS "\:(.+)$"|%{$SSID=$_.Matches.Groups[1].Value.Trim(); $_}|%{(netsh wlan show profile name="$SSID" key=clear)}|SLS "Conte.*:(.+)$"|%{$pass=$_.Matches.Groups[1].Value.Trim(); $_}|%{[PSCustomObject]#{SSID=$SSID;PASSWORD=$pass}}
$var | Format-List | Out-File -FilePath ".\WifiKeys_List_Format.txt"
$var | ConvertTo-Json | Out-File -FilePath ".\WifiKeys_JSON_Format.txt"
$var | OGV -Title "Wifi Passwords Recovery by Hackoo 2022" -wait
ii ".\WifiKeys_JSON_Format.txt"
ii ".\WifiKeys_List_Format.txt"

Renaming incrementing integer name to incrementing integer

can you show me a way to solve following problem with Powershell or CMD?
This is my file names in folder.
002.mp3
003.mp3
.
.
.
604.mp3
I want to change that numbers to;
001.mp3
002.mp3
003.mp3
.
.
.
603.mp3
But important thing is, it has to be like that
002.mp3 to 001.mp3
003.mp3 to 002.mp3
...
...
...
604.mp3 to 603.mp3
thank you very much.
You can do the following:
$files = Get-ChildItem -Path "C:\PathToMP3Files\[0-6][0-9][0-9].mp3" -File
$files | Rename-Item -NewName {"{0:D3}.mp3" -f ([int]$_.BaseName - 1)} -whatif
Just remove the -whatif parameter to perform the rename if you are satisfied with the results.
Explanation:
The -Path parameter of Get-ChildItem supports wildcards. Using a wildcard range [0-6] (one character from the set 0 to 6), you can narrow down your target items.
Since New-Item's -NewName supports delay-script binding, you can pipe your FileInfo objects directly into the command. The -NewName parameter manipulates the Name property of the object. The code above is using BaseName, which is the Name without the extension, because it is an easy way to perform digit increase.
-f is the string format operator. It performs a substitution of {number} values within a string. The number corresponds to an item's index in the collection provided to the right of the -f.
This is simpler in a Batch file, and run faster than PS too! (just try it)
#echo off
setlocal EnableDelayedExpansion
for /F %%a in ('dir /B *.mp3') do set /A "n=1%%~Na-1" & ren "%%a" "!n:~1!.mp3"
Yoy may even do it directly at the command prompt with no need of a .bat file; just be sure that n variable does not exists (executing set "n=" before):
for /F %a in ('dir /B *.mp3') do #set /A "n=1%~Na-1" & call ren "%a" "%n:~1%.mp3"

rename 2nd extension but allow for duplicates

I have a server that was infected with ransomware. I have decrypted most of it, but now have files that are a changed filetype or that have been renamed that I need to check:
newsfeed.xml.BLACK_MAMBA_Files#QQ.COM.BLACK_MAMBA_Files#QQ
Google Chrome.lnk.BLACK_MAMBA_Files#QQ
I tried
ren *.BLACK_MAMBA_Files#QQ* *.
I was thinking this would rename all the files, removing the extra text but keeping the original file extension. The error I received was
A duplicate file name exists or the file cannot be found.
I have very limited experience with the command prompt and no experience with PowerShell. If anyone can advise how I should go about this or an alternative, I would appreciate it.
This will rename files to remove the .BLACK_MAMBA_Files suffix in any form:
Get-ChildItem C:\folder -Recurse | Where-Object { $_.Name -like "*BLACK_MAMBA_Files*" } | Rename-Item -NewName { $_.Name -replace ".BLACK_MAMBA_Files.*",""} -WhatIf
NOTE:
I've added -WhatIf as I've only tested this with the two examples you've included. I'm confident it will work fine but it's best to test it first.
With this parameter included you can run the command and it will only display the the results of the rename command, but not actually complete the rename for real.
Remove -WhatIf from the end when you've confirmed that the rename process works correctly with your files.
Edit Reworked the script to work with a RegEX
If the extension is appended multiple times,
run this script as often to remove all occurences.
PushD 'X:\folder\to\start'
$Pattern = '(\.COM)*\.BLACK_MAMBA_Files#QQ'
Get-ChildItem -Recurse -File -Filter "*BLACK_MAMBA*"|
Where Name -match $Pattern|
ForEach {
If (!(Test-Path ($_.FullName -replace $Pattern))) {
$_|Rename-Item -NewName {$_.Name -Replace $Pattern} -confirm
} Else {
"can't rename $($_.FullName) ยด`r`nbecause $($_.FullName -Replace $Pattern) already present"
}
}
PopD
If the script works OK, remove the -Confirm at the end of the Rename-Item.
You Can try this but you should test it first
Get-ChildItem -Path c:\PathtoDirectory -recurse |
Where {$_.FullName -Like "*.*BLACK*"} |
Foreach {Rename-item -Path $_.FullName -NewName $_.BaseName}
With the below command you can see the orignal file name is now the base name so we can use that property to rename them.
Get-Item -Path C:\PathtoFile | select *
You will have to run the command twice for the files with .com on the extention.
#ECHO OFF
SETLOCAL enabledelayedexpansion
SET "sourcedir=U:\sourcedir"
SET "outfile=U:\report.txt"
(
FOR /f "delims=" %%a IN (
'dir /b /s /a-d "%sourcedir%\*.BLACK_MAMBA_Files#QQ*" '
) DO (
SET "newname=%%a"
SET "newname=!newname:.BLACK_MAMBA_Files#QQ=?!"
FOR /f "delims=?" %%r IN ("!newname!") DO ECHO REN "%%a" "%%~nxr"
)
)>"%outfile%"
GOTO :EOF
You would need to change the setting of sourcedir to suit your circumstances.
This simple batch should put you on the path. I used my u: ramdrive for testing.
Starting at the directory you define as sourcedir, perform a directory list for filenames only (no directorynames) including subdirectories. Assign each name found matching the mask ".BLACK_MAMBA_Files#QQ" to %%a.
Using the facilities available with delayed expansion, assign %%a to newname, then replace each occurrence of the target string with ?, which is an illegal filename character.
Then use the default tokens=1 with delims=? to assign the first part of the resultant name in newname - up to the first delimiter (which is ?) to %%r.
Then rename using just the name and extension parts of %%r (as that's the only part ren will accept).
I chose to output the ren commands by parenthesising the entire nested for statement and redirecting the output to the file defined as outfile. If this was a .bat file, then you should examine it for sanity and then just run the output file as another batch if it appears to be appropriate. This also allows you to retain a record of the modifications done.

Replace Single Quotes (') in Filenames

I received a good suggestion in another thread to support the removal/replacement of specific characters from filenames in a directory structure. Works as expected for common ascii characters (like &).
PowerShell (works fine to remove & character from filenames):
powershell.exe -c "Get-ChildItem 'c:\Media\Downloads' -Filter '*&*' -Recurse | Rename-Item -NewName {$_.name -replace '&','' }"
I also need remove single quotes from some files: Example: mark's_file.txt.
I've tried a few variants without success. I think I am running into a punctuation issue I am unable sort out. I also tried using a variable = char(39) and adding to the string. No luck.
Any ideas to accomplish?
Note: Would like a self contained batch file approach, vs calling an external .ps1 file.
A Batch file also works fine to remove both & and ' characters from filenames:
#echo off
setlocal EnableDelayedExpansion
rem Remove "&" characters:
for /R "c:\Media\Downloads" %%a in ("*&*") do (
set "fileName=%%~NXa"
ren "%%a" "!filename:&=!"
)
rem Remove "'" characters:
for /R "c:\Media\Downloads" %%a in ("*'*") do (
set "fileName=%%~NXa"
ren "%%a" "!filename:'=!"
)
... but the Batch file start run much faster than the PS one!

Trying to copy a group of files contained in a text file

I'm trying to copy a list of files from a txt file and as a newbie, I'm having a hard time.
Here is a bit of the text file. The real file has no extra lines, but I had to do that to :
"D:\Shared\Customer Care\Customer Care Common\Customers Contracted\Customers Contracted\Fred 44705"
"D:\Shared\Customer Care\Customer Care Common\Customers Contracted\Customers Contracted\Johnson 47227"
"D:\Shared\Customer Care\Customer Care Common\Customers Contracted\Customers Contracted\Daniel 35434"
"D:\Shared\Customer Care\Customer Care Common\Customers Contracted\Customers Contracted\Frank, John 48273"
I've tried enclosing the filename string in double-quotes as well.
Here's the simple script I'm trying to use:
Get-Content c:\users\scripts\files-to-fix.txt | Foreach-Object {copy-item $_ d:\junk}
The error I'm getting is:
Copy-Item : Cannot find drive. A drive with the name ''D' does not
exist. At C:\users\mhyman\scripts\copyfiles.ps1:2 char:81
+ Get-Content c:\users\mhyman\scripts\files-to-fix.txt |
Foreach-Object {copy-item <<<< $_ d:\junk}
+ CategoryInfo : ObjectNotFound: ('D:String) [Copy-Item],
DriveNotFoundException
+ FullyQualifiedErrorId :
DriveNotFound,Microsoft.PowerShell.Commands.CopyItemCommand
I know this is simple, but I would really appreciate some help.
I think it is the surrounding quotes that are causing the problem ( as indicated by the error saying that a drive of name "D is not found. Try this:
get-content c:\users\scripts\files-to-fix.txt | %{ copy-item $_.trim('"') d:\junk}
Of course, if you can control the txt file, enter the list without the quotes.
By your tags and drive letters and backslashes it is clearly a Windows environment your working in and although I'm not a PowerShell scripter, I'm a better than most batch scipter and use a For / If conditioanla statement sicne it is shorter and you feed it your file instead of parsing out the file into reduudc commands on a line, so in your example:
for /F %%t in (the text file.txt) do copy /q %%t d:\junk
And then you go home and never worry about until the next morning
Does powershell have a runas ornative mode that can parse older, more proven and stable DOS commands ?