Renaming incrementing integer name to incrementing integer - powershell

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"

Related

Want to retrieve the Modified date for list of file names present inside a file in CMD prompt

I have a list of file names present inside a file called My_text.txt, may be more than 100. I want to retrieve the Date modified, basically the DIR command output for all those file names.
My_Text.txt contains
D:\Users\dsa99_p\Desktop\My_Program1.txt
D:\Users\dsa99_p\Desktop\My_Program2.txt
D:\Users\dsa99_p\Desktop\My_Program3.txt
D:\Users\dsa99_p\Desktop\My_Program4.txt
and so on..
I want to retrieve the Date modified for all these My_Program1, My_Program2, My_Program3, My_Program4 files. How to do it? Please help.
If it's possible over Powershell then let me know.
In PowerShell the file content can be loaded by Get-Content and file information can be obtained with Get-ChildItem. So this is how it can be done in PowerShell:
Get-Content My_text.txt | ForEach-Object { (Get-ChildItem $_).LastWriteTime }
(Get-ChildItem (Get-Content My_text.txt)).LastWriteTime
Both commands do the same thing. Shorter form of them:
gc My_text.txt |% { (ls $_).LastWriteTime }
(ls (gc My_text.txt)).LastWriteTime
If you want a batch file solution
FOR /F "usebackq delims=" %%G IN ("My_Text.txt") DO ECHO FileName:%%G Modified:%%~tG
Because it is possible that one or more of the files may not exist, I would probably structure my code a little differently. I would first check whether each line related to an existing file, and only then get its information.
The first example I'll provide is for PowerShell, whilst it may seem like more text, it will be far more configurable, especially with regards to modifying the layout and content of the results.
powershell command line:
(Get-Content -Path '.\My_Text.txt') | ForEach-Object { If (Test-Path -LiteralPath $_ -PathType Leaf) { Get-Item -LiteralPath $_ | Select-Object -Property LastWriteTime, Name } }
cmd command line:
For /F "UseBackQ Delims=" %G In (".\My_Text.txt") Do #If "%~aG" Lss "d" If "%~aG" GEq "-" Echo %~tG: %~nxG
Single line batch-file version:
#(For /F "UseBackQ Delims=" %%G In (".\My_Text.txt") Do #If "%%~aG" Lss "d" If "%%~aG" GEq "-" Echo %%~tG: %%~nxG)&Pause
In all examples above, I have assumed that My_Text.txt is in the current directory, if it isn't please change its currently relative location .\ as necessary without modifying its quoting.

batch add a character(s) in the middle of a filename using cmd

So I have files (mostly documents) with a file name beginning with "YYYYMMDD - Title of file.etc"
I'm wanting to change the date format to YYYY-MM-DD
I'm wanting to do a script to batch rename since I'll be doing this every now and then.
My bat code so far after a 2 days of research to no avail:
for %%a in ("*.*") do ren *.* ????-??-??*.*
pause
Any help or point to the right direction for me to look at would be really helpful. Thanks
final
rem // Loop through all matching files:
for /F "eol=| delims=" %%F in ('
dir /B /A:-D-H-S "*.*"
') do (
rem // Store the current file name and extension to variables:
set "NAME=%%~F"
rem // Enable delayed expansion to avoid trouble with `!`:
setlocal EnableDelayedExpansion
rem // Rename file by applying sub-string expansion:
ren "!NAME!" "!NAME:~,4!-!NAME:~4,2!-!NAME:~6!!EXT!"
endlocal
)
pause
You are utilising a for loop but not using its meta-variable %%a in the body then, which makes no sense.
Unfortunately, you cannot just use ren for that, because every ? in the new name represents the character of the old name at that position.
I would do it the following way:
rem // First change to the target directory:
cd /D "D:\Target\Dir"
rem // Loop through all matching files:
for /F "eol=| delims=" %%F in ('
dir /B /A:-D-H-S "*.*" ^| findstr /I "^[1-2][0-9][0-9][0-9][0-1][0-9][0-3][0-9]"
') do (
rem // Store the current file name and extension to variables:
set "NAME=%%~nF" & set "EXT=%%~xF"
rem // Enable delayed expansion to avoid trouble with `!`:
setlocal EnableDelayedExpansion
rem // Rename file by applying sub-string expansion:
ren "!NAME!!EXT!" "!NAME:~,4!-!NAME:~4,2!-!NAME:~6!!EXT!"
endlocal
)
The [findstr][cmdfnd] is used here to filter for file names that begin with eight decimal digits that could represent a date. If you do not want that simply remove everything from ^| findstr up to the end of that line.
Delayed variable expansion is needed here, because you are writing and reading variables within the same block of code. Splitting the original name at fixed character positions is done by sub-string expansion.
(How-To: Extract part of a variable (substring))
[cmdfnd]: https://ss64.com/nt/findstr.html
(FINDSTR)
RightHanded,
Maybe you should look at Powershell commands.
The following powershell command replaces spaces with underscores of all files of the current directory :
dir | rename-item -NewName {$_.name -replace " ","_"}
Source : https://www.howtogeek.com/111859/how-to-batch-rename-files-in-windows-4-ways-to-rename-multiple-files/
You can see how to modify Powershell strings here for example : https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/convert-string?view=powershell-5.1
Powershell will be much easier to do this. Use this:
#echo off
pushd "The Directory"
powershell -command "& {get-childitem | foreach {$NewName = $_.Name -replace '\d{8}.*', '\d{4}-\d{2}-\d{2}.*'; rename-item -path '.\$_.Name' -newname '$NewName'}}"
popd
goto :eof
You can use this as a function to rename the files to the format you want. You can call this function inside a loop FOR, if you want.
set old_filename=YYYYMMDD - Title of file.etc
:: Extract only the first 4 characters
SET yyyy=%old_filename:~0,4%
:: Skip 4 characters and then extract the next 2
SET mm=%old_filename:~4,2%
:: Skip 6 characters and then extract the next 2
SET dd=%old_filename:~6,2%
:: Skip 8 characters and then extract everything else
SET everything_else=%old_filename:~8%
:: Rename de old filename to the new
rename "%old_filename%" "%yyyy%-%mm%-%dd%%everything_else%"

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!

How to interrogate multiple text files for certain key words and output results in text?

Here is my objective:
I have a networked folder (Windows 7) that contains text log files that are generated on daily basis (1 log text per day), as a result file names contain various dates.
I need a script to go in and scan each new log file for a list of certain keywords: "ABC", "DEF", "GHI". Then write out how many of these events were found in each log file and save this info in a text format or similar.
Issues I'm facing: how do i get around various file names, each file name contains that days date. How do i look through a list of keywords and count all of these words in each log file. How do i write out the results in a separate text file. And finally is there a way to automate all of this?
I would like to stay in PowerShell or use Windows batch files.
I am afraid your request is not clear and have several missing details. However, here it is a Batch file with what I guess could be the first attempt to get a solution:
EDIT: I modified the original code in order to also group the files per event; the first code just groups events per file.
#echo off
setlocal EnableDelayedExpansion
rem Push dir to the networked folder
pushd "\\Path\to\networked\folder"
rem Count all file/event combinations in a two-dimensional array
for %%a in (ABC DEF GHI) do (
for /F "delims=:" %%b in ('findstr /I /L "%%a" logFiles*.txt') do (
set /A "count[%%~Nb][%%a]+=1"
)
)
rem Group events for the same file
for /F "tokens=2,3* delims=[]=" %%a in ('set count[') do (
set "file[%%a]=!file[%%a]!, %%b (%%c)"
)
rem Show the final result 1: events per file
(
echo Events per file:
for /F "tokens=2* delims=[]=" %%a in ('set file[') do (
set "line=%%b"
echo %%a.txt = !line:~2!
)
) > result1.txt
rem Group and count files for the same event
for /F "tokens=2,3* delims=[]=" %%a in ('set count[') do (
set "event[%%b]=!event[%%b]!, %%a.txt (%%c)"
set /A "eventCount[%%b]+=%%c"
)
rem Show the final result 2: files per event
(
echo Files per event:
for /F "tokens=2* delims=[]=" %%a in ('set event[') do (
set "line=%%b"
echo "%%a" - !eventCount[%%a]! found in !line:~2!
)
) > result2.txt
In PowerShell we can use Get-Childitem to collect which files we want to search though and store those in a variable as such:
$Content = Get-Content (Get-Childitem -Path C:\Temp\*.txt)
Once those text files are stored into our Content variable we can simply use the -match regex operator to find a match inside that collection of files.
$Content -match "Bacon"
You could then out this information using Out-File:
$Content -match "Bacon" | Out-file C:\Temp\Bacon.txt
Of course with the Get-child item you can use the DateTime operator and narrow down your query for only recently changed text files as required.
If you want to get more technical we can use Select-String to get this output for multiple matches as such:
Get-ChildItem C:\Logs |
where { $_ | Select-String -Pattern 'Blahblah' } |
where { $_ | Select-String -Pattern '\d{4}' } |
...
You can also do it on one line:
gci C:\Logs| select-string -pattern '(Bacon.*Failed)|(Failed.*Steak)'
Outputting is up to your imagination really. Once they are just simple strings they can be put into an array or a custom PS object for nice output. it would just require you to save the command you were running into a variable then call it later for the export.
for Grouping, take a look at Group-Object cmdlet. it will give you the occurrence numbers.