1

I would like to recurse through all subfolders of a given folder, and for all files of a given extension (optionally wildcard), search and replace some piece of text.

There's a similar previous question here, and I'm trying to get a modified version of the top answer working for my purpose. It uses Powershell for the find and replace. However, my modified version below is not recursing. I don't remember where I found the recurse part of the first line, so maybe I'm using that incorrectly.

Get-ChildItem *.* -exclude *.ps1* -recurse |
Foreach-Object {
    $c = ($_ | Get-Content) 
    $c = $c -replace 'foo','bar'
    [IO.File]::WriteAllText($_.FullName, ($c -join "`r`n"))
}

I am running the code from the Powershell command line as a PS batch file, .ps1, hence the exclusion of that extension.

This works fine if I run it directly in a folder that has some files I want searched, but if I run it from a parent of that folder, the searching/ recursion of subfolders does not happen. It doesn't even try to, which I can tell from the fact that the command finishes running instantaneously. If I run it in my first subfolder, which has about 50 text files, there's a couple seconds delay before it finishes, indicating to me it's actually searching those files.

I've also tried this with the exclude portion removed and the behaviour is the same.

Community
  • 1
  • 1
SSilk
  • 2,433
  • 7
  • 29
  • 44
  • If you run this from the parent dir `Get-ChildItem *.* -exclude *.ps1* -recurse`, you get nothing? I can't repro that (on V4). – Keith Hill Oct 29 '13 at 13:39
  • Just double-checked. If I run from the parent of the directory with the files I want checked, nothing happens: a Notepad++ search for the content I wanted changed is the same before and after. If I then run the code from within the folder, a) the changes are made (can't find the replaced text anymore using NPP), and b) all files in the folder show an updated modified date. I'm not sure what PS version I'm running though. When I go to the powershell exe, I find it's located in `\WindowsPowerShell\v1.0\` but if I run `$PSVersionTable.psversion` it tells me I'm running V2.0. Any thoughts? Thanks. – SSilk Oct 29 '13 at 15:05
  • You running v2. Take a look at the help on Get-ChildItem and its Exclude parameter to see if it says anything about that parameter behaving oddly. – Keith Hill Oct 29 '13 at 15:10
  • @KeithHill: I've also tried this with the exclude portion removed, i.e. `Get-ChildItem *.* -recurse |` for the first line of my code and the behaviour is the same. – SSilk Oct 29 '13 at 15:14
  • Try `Get-ChildItem -recurse -force` in case the files might be hidden. – Keith Hill Oct 29 '13 at 15:18
  • @KeithHill: Just tried that and it didn't work. Again, there's no indication it's even trying to go into the subfolders. Is there a way to put some or all of the commands into a verbose mode so I can maybe see if it's even trying to dig down? – SSilk Oct 29 '13 at 15:23
  • Remove the `*.*`, it will go in all folders by default – Eris Oct 29 '13 at 16:03
  • If you want verbose, `Set-PSDebug -Trace 2` will spew inordinate amounts of information to your Host – Eris Oct 29 '13 at 16:22
  • @Eris: removing `*.*` did it. That's weird. Why would having `*.*` in there make it not recurse, and is there a way to recurse with that in there? What if I do want to recurse but with some file filter? If you're able to add that as an answer with some brief explanation of why that caused the failure I'll accept it. Thanks. – SSilk Oct 29 '13 at 17:47

1 Answers1

1

My guess is that *.* matches only items with a dot in them. Folders have no extension, so they aren't matched.

gci -rec -force -exclude *.ps1 | should do what you want.

Eris
  • 7,378
  • 1
  • 30
  • 45