Powershell/Windows Batch/VB Script: replace string in folders and files

Hello experts,

I am looking for a batch, powershell or vbscript to cover the following requirement:

-Loop a reported folder with drill down
-Check the various files and folder
-Replace SourceString by TargetString
-SourceString and TargetString should be reported as parameter

-Example:
BaseDir= C:\Test
SourceString= “_”
TargetString “-“

-Various files and folders which contains source string “_” should be replaced by target  “-“.

If you have questions, please contact me.
Thank you.
LVL 1
LD16Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Bill PrewIT / Software Engineering ConsultantCommented:
Are the replacements being made in the file name?  Of folders and files, or just files?  Or the extension?


»bp
oBdACommented:
Save this as Rename-ItemRecurse.ps1 or Whatever.ps1 (not in test mode, see below).
You can pass the start path, the source string, and the target string as parameters; if an argument is not passed, the defaults will be taken  from the command line.
In addition, you can use the following arguments:
-Verbose
-WhatIf (test mode, will not rename anything)
-Confirm (will list and prompt before renaming anything)
Examples:
.\Rename-ItemRecurse.ps1 -Path C:\toto -WhatIf
.\Rename-ItemRecurse.ps1 -Confirm

Open in new window

[CmdletBinding(SupportsShouldProcess=$true)]
Param(
	[Parameter(Position=0)]
	[string]$Path = 'C:\Test',
	[Parameter(Position=1)]
	[string]$SourceString = '_',
	[Parameter(Position=2)]
	[string]$TargetString = '-'
)
$verbose = $PSBoundParameters.ContainsKey('Verbose') -and $PSBoundParameters['Verbose'].ToBool()
$pattern = [regex]::Escape($SourceString)

Get-ChildItem -Path $Path -File -Recurse |
	Where-Object {$_.Name -match $pattern} |
	Rename-Item -NewName {$_.Name -replace $pattern, $TargetString} -Verbose:$verbose

Get-ChildItem -Path $Path -Directory -Recurse |
	Where-Object {$_.Name -match $pattern} |
	Sort-Object -Property @{e={$_.FullName.Split('\').Count}} -Descending |
	Rename-Item -NewName {$_.Name -replace $pattern, $TargetString} -Verbose:$verbose

Open in new window

Bill PrewIT / Software Engineering ConsultantCommented:
If you are just talking about doing the replacements in file names (not folder names) then this should work.

@echo off
setlocal EnableDelayedExpansion

set BaseDir=B:\EE\EE29144987\test
set SourceString=_
set TargetString=-

for /f "tokens=*" %%A in ('dir /b /s /a-d "%BaseDir%\*%SourceString%*.*"') do (
    set FileName=%%~nA
    set FileName=!FileName:%SourceString%=%TargetString%!
    ren "%%~A" "!FileName!%%~xA"
)

Open in new window


»bp
Bootstrap 4: Exploring New Features

Learn how to use and navigate the new features included in Bootstrap 4, the most popular HTML, CSS, and JavaScript framework for developing responsive, mobile-first websites.

LD16Author Commented:
Hello,
Is it possible to have flag to calibrate the procedure. 1 for file names 2 for folder names.
Batches and powershell approaches?
Thank you very much for your help.
The procedure concerns file names and not extensions.
oBdACommented:
On closer inspection, seems like I misinterpreted your "parameters".
This now has the settings hardcoded (test/confirm/verbose modes still available as described above).
Processing of files and/or folders can be enabled or disabled individually (currently does both).
It is now in test mode (variable $testMode), and when processing files, it will ignore extensions when matching.
$baseDir = 'C:\Test'
$sourceString = '_'
$targetString = '-'
$processFiles = $true
$processFolders = $true
$testMode = $true
$confirm = $false
$verbose = $true

$pattern = [regex]::Escape($SourceString)
If ($processFiles) {
	Get-ChildItem -Path $baseDir -File -Recurse |
		Where-Object {$_.BaseName -match $pattern} |
		Rename-Item -NewName {"$($_.BaseName -replace $pattern, $TargetString)$($_.Extension)"} -Verbose:$verbose -WhatIf:$testMode -Confirm:$confirm
} Else {
	Write-Warning 'Processing of files is disabled!'
}
If ($processFolders) {
	Get-ChildItem -Path $baseDir -Directory -Recurse |
		Where-Object {$_.Name -match $pattern} |
		Sort-Object -Property @{e={$_.FullName.Split('\').Count}} -Descending |
		Rename-Item -NewName {$_.Name -replace $pattern, $TargetString} -Verbose:$verbose -WhatIf:$testMode -Confirm:$confirm
} Else {
	Write-Warning 'Processing of folders is disabled!'
}

Open in new window

Shaun VermaakTechnical SpecialistCommented:
I would just use fnr.exe - Find And Replace Tool for this
358a59e5-8789-4779-b131-0cf89b5a0286.pnghttps://archive.codeplex.com/?p=findandreplace
Bill PrewIT / Software Engineering ConsultantCommented:
This should handle folders as well as files now, driven by a variable.

@echo off
setlocal EnableDelayedExpansion

set BaseDir=B:\EE\EE29144987\test
set SourceString=_
set TargetString=-
set ProcessFiles=Y
set ProcessFolders=Y

if /i "%ProcessFiles%" EQU "Y" (
    for /f "tokens=*" %%A in ('dir /b /s /a-d "%BaseDir%\*%SourceString%*.*"') do (
        set FileName=%%~nA
        set FileName=!FileName:%SourceString%=%TargetString%!
        ren "%%~A" "!FileName!%%~xA"
    )
)

if /i "%ProcessFolders%" EQU "Y" (
    for /f "tokens=*" %%A in ('dir /b /s /ad "%BaseDir%\*%SourceString%*.*" ^| sort /r') do (
        set FileName=%%~nA
        set FileName=!FileName:%SourceString%=%TargetString%!
        ren "%%~A" "!FileName!%%~xA"
    )
)

Open in new window


»bp

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
LD16Author Commented:
Thank you very much! Unable to test right now I will keep you informed!
LD16Author Commented:
Question: espace " " Can be reported as SourceString?
Example: replace " " by  "-".
SourceString= " "
TargetString= "-"
oBdACommented:
Yep.
LD16Author Commented:
Thank you.
Bill PrewIT / Software Engineering ConsultantCommented:
To replace a space in the BAT approach, you would do this (there is one space after the equal sign):

set "SourceString= "

not:

set SourceString=" "


»bp
LD16Author Commented:
Noted. Thank you very much!
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Powershell

From novice to tech pro — start learning today.