Nemo XXX
Nemo XXX

Reputation: 681

How to change the file extension of files that contain a certain string with PowerShell

I'm trying to automatically rename all *.txt files to *.log files, but only if they contain the upper case string ERROR.

However, the following code doesn't work:

Get-ChildItem *.txt -file | Select-String "ERROR" | Rename-Item -NewName { $_.Name -replace '.txt','.log' }

I'm getting the following error message:

Rename-Item : Cannot bind argument to parameter 'NewName' because it is an empty string.

I found out that I can get the actual path with:

Get-ChildItem *.txt -file | Select-String "ERROR" | ForEach-Object { Write-Host $_.Path }

but I can't figure out how to use it with Rename-Item.

I also tried:

Get-ChildItem *.txt -file | Select-String "ERROR" | [io.path]::ChangeExtension($_.name, "log")

but I got the following error message:

Expressions are only allowed as the first element of a pipeline.

Upvotes: 2

Views: 103

Answers (2)

mklement0
mklement0

Reputation: 437042

Select-String -Path *.txt -List -CaseSensitive 'ERROR' |
  Rename-Item -NewName { $_.FileName -replace '\.txt$', '.log' } -WhatIf

Note: The -WhatIf common parameter in the command above previews the operation. Remove -WhatIf and re-execute once you're sure the operation will do what you want.

  • Use -CaseSensitive to ensure case-sensitive matching.

  • Use -List to stop searching after the first match in a given file has been found, as an optimization.

  • Take advantage of Select-String's -Path parameter that directly accepts a wildcard pattern of files to look for - no need for a separate Get-ChildItem call in this case.

  • Since it is the Microsoft.PowerShell.Commands.MatchInfo instances emitted by Select-String that provide the input to Rename-Item - via their .Path property - you must use their .FileName property to refer to the file name in the calculated property passed to -NewName.

Upvotes: 2

Mathias R. Jessen
Mathias R. Jessen

Reputation: 174425

Use Where-Object to filter the file system items based on what Select-String finds:

Get-ChildItem *.txt -file |Where-Object { $_ |Select-String "ERROR" -CaseSensitive } |Rename-Item -NewName { $_.Name -replace '.txt','.log' }

Upvotes: 2

Related Questions