Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to replace string in files and file and folder names recursively with PowerShell?

With PowerShell (although other suggestions are welcome), how does one recursively loop a directory/folder and

  1. replace text A with B in all files,
  2. rename all files so that A is replaced by B, and last
  3. rename all folders also so that A is replaced by B?
like image 367
Martin R-L Avatar asked Apr 13 '11 13:04

Martin R-L


People also ask

How do I replace text in multiple files in PowerShell?

Using the PowerShell replace() method or PowerShell replace operator, we can replace strings in multiple files. Using the Get-ChildItem cmdlet gets the item from the specified location and piped the output to the Get-Content to read the file, we can call replace method to replace strings in multiple files.

How do I replace a string in a PowerShell file?

Finding and Replacing the String One way to do that is to use the -replace operator. This PowerShell operator finds a string and replaces it with another. Using the example file contents, we can provide the search string foo with the replacement string bar which should make the file contents foo foo baz now.

How do you replace a string in all files in a directory in Windows?

Remove all the files you don't want to edit by selecting them and pressing DEL, then right-click the remaining files and choose Open all. Now go to Search > Replace or press CTRL+H, which will launch the Replace menu. Here you'll find an option to Replace All in All Opened Documents.

How do I change directory and drives in PowerShell?

Typing CD\ causes PowerShell to move to the root directory. As you can see, you can use the CD.. or CD\ command to move to a lower level within the folder hierarchy. You can also use the CD command to enter a folder. Just type CD, followed by the folder name.


2 Answers

With a few requirements refinements, I ended up with this script:

$match = "MyAssembly" 
$replacement = Read-Host "Please enter a solution name"

$files = Get-ChildItem $(get-location) -filter *MyAssembly* -Recurse

$files |
    Sort-Object -Descending -Property { $_.FullName } |
    Rename-Item -newname { $_.name -replace $match, $replacement } -force



$files = Get-ChildItem $(get-location) -include *.cs, *.csproj, *.sln -Recurse 

foreach($file in $files) 
{ 
    ((Get-Content $file.fullname) -creplace $match, $replacement) | set-content $file.fullname 
}

read-host -prompt "Done! Press any key to close."
like image 199
Martin R-L Avatar answered Sep 20 '22 22:09

Martin R-L


I would go with something like this:

Get-ChildItem $directory -Recurse |
    Sort-Object -Descending -Property { $_.FullName } |
    ForEach-Object {
        if (!$_.PsIsContainer) {
            ($_|Get-Content) -replace 'A', 'B' | Set-Content $_.FullName
        }
        $_
    } |
    Rename-Item { $_.name -replace 'A', 'B' }

The Sort-Object is there to ensure that first children (subdirs, files) are listed and then directories after them. (12345)

like image 22
stej Avatar answered Sep 19 '22 22:09

stej