How do I change extension file in Powershell? - powershell

I want to change extension of some of my file.
I tried this code, but it still return error
The input to the script block for parameter 'NewName' failed.
Anyone can help please?
$b = "TA"
$c = "70"
$Path_1 = "C:\Users\hh\Documents"
$Found = Get-ChildItem -Name "$Path_1\*$b-$c*.txt" | Rename-Item -NewName { $_.Name.Replace('.txt','.csv') }

This should do it:
$b = "TA"
$c = "70"
$Path_1 = "C:\Users\hh\Documents"
$Found = Get-ChildItem -Filter ($Path_1 + "\*" + $b + "-" + $c + "*.txt")
foreach ($entry in $Found){
Rename-Item -Path $entry.FullName -NewName ($entry.Name.Replace('.txt','.csv'))
}

In this case, it is much easier to use both the -Path and -Filter parameters on the Get-ChildItem cmdlet.
If you want to make sure you do not by accident change folder names, in PowerShell version 3.0 and up, add the -File switch aswell like I'm doing here:
$b = "TA"
$c = "70"
$Path_1 = "C:\Users\hh\Documents"
Get-ChildItem -Path $Path_1 -Filter "*$b-$c*.txt" | Rename-Item -NewName { '{0}.csv' -f $_.BaseName } -WhatIf
# For PowerShell versions below 3.0, you need to add an extra Where-Object clause:
# Get-ChildItem -Path $Path_1 -Filter "*$b-$c*.txt" | Where-Object { !$_.PSIsContainer } | Rename-Item -NewName { '{0}.csv' -f $_.BaseName } -WhatIf
Of course, you can also use .NET [System.IO.Path]
Get-ChildItem -Path $Path_1 -Filter "*$b-$c*.txt" | Rename-Item -NewName { [System.IO.Path]::ChangeExtension($_.Name, ".csv") } -WhatIf
Remove the -WhatIf switch if you are satisfied with the results.

The rest of the error message is "You cannot call a method on a null-valued expression". "get-childitem -name" only outputs a string, not an object with properties. Take out the -name after get-childitem, and it would work.

Related

Adding _ at the end of every file name of 3 type of extension in a folder

How could I modify name of every file by adding _ before the filename extension in a Get-ChildItem -Include without calling 3 times a Foreach.
My script works, but I would like to simplify it by using -Include and not -Filter.
function renommer_fichier {
$files = Get-ChildItem -Path C:\mestp\mesFichiers -Filter *.jpg
Foreach ($file in $files)
{
$file | Rename-Item -NewName { $_.Name -replace '.jpg', '_.jpg' }
}
$files = Get-ChildItem -Path C:\mestp\mesFichiers -Filter *.mp3
Foreach ($file in $files)
{
$file | Rename-Item -NewName { $_.Name -replace '.mp3', '_.mp3' }
}
$files = Get-ChildItem -Path C:\mestp\mesFichiers -Filter *.mpeg
Foreach ($file in $files)
{
$file | Rename-Item -NewName { $_.Name -replace '.mpeg', '_.mpeg' }
}
}
Unfortunately, the -Include parameter - which supports specifying multiple patterns - doesn't work as one would intuitively expect:
Use Get-Item instead of Get-ChildItem and append \* to the input path to make -Include work as intended.
See this answer for background information.
Use the .BaseName and .Extension properties in the delay-bind script block you're passing to Rename-Item to facilitate inserting _ before the filename extension.
Get-Item -Path C:\mestp\mesFichiers\* -Include *.jpg, *mp3, *.mpeg |
Rename-Item -WhatIf -NewName { $_.BaseName + '_' + $_.Extension }
Note: The -WhatIf common parameter in the command above previews the operation. Remove -WhatIf once you're sure the operation will do what you want.

Add filename increment in my script

I have created a script that will rename pst files to acl owner. It works. The only problem i have is when there are two pst files in the same folder.It gives them the same name. How can i add an increment in my script. It ried it with Si = 1 and Si++ but with no results.
Here is my script:
Get-ChildItem C:\Users\tester\* -Filter *.pst -recurse |
ForEach-Object{
$owner = ( $_ | Get-Acl ).Owner.Split("\")[1]
$newname = "$owner.pst"
$_ | Rename-Item -NewName $newname -Verbose -WhatIf
}
This is a quick and fast work around by adding names already used to an array and checking each time you loop.
$increment = 1
$alreadyProcessed = #()
Get-ChildItem C:\Users\tester\* -Filter *.pst -recurse |
ForEach-Object{
$owner = ( $_ | Get-Acl ).Owner.Split("\")[1]
$newname = "$owner.pst"
if($alreadyProcessed.Contains($newName))
{
$newName = "$owner`$increment.pst"
$increment++
}
$alreadyProcessed += $newname
$_ | Rename-Item -NewName $newname -Verbose -WhatIf
}
This will ensure a unique name each time.
If you plan to run your script multiple times in the same place then you should check to see what names are available otherwise your counter will reset to 1 but those files would already exist.
function Get-NextName ($file) {
$existing = (Get-Item "$file.*").Name
$i = 1
while ($existing -contains "$file.$i") {
$i++
}
"$file.$i"
}
And then adjust your function:
Get-ChildItem C:\Users\tester\* -Filter *.pst -recurse |
ForEach-Object{
$owner = ( $_ | Get-Acl ).Owner.Split("\")[1]
$newname = Get-NextName "$owner.pst"
$_ | Rename-Item -NewName $newname -Verbose -WhatIf
}

Powershell renaming files recursively, not renaming duplicates

I have some powershell code that is meant to take specific characters out of file names recursively. This works great, unless taking the characters out causes 2 files to match names in the same folder.
I found the Powershell here PowerShell script to remove characters from files and folders but it doesn't solve the issue I am having.
$characters = "$#"
$regex = "[$([regex]::Escape($characters))]"
$filesandfolders = Get-ChildItem -recurse "D:\projects\filenameCleaner\TEST" | Where-Object {$_.name -match $regex}
$filesandfolders | Where-Object {!$_.PsIscontainer} | foreach {
$New=$_.name -Replace $regex
Rename-Item -path $_.Fullname -newname $New -passthru
}
$filesandfolders | Where-Object {$_.PsIscontainer} | foreach {
$New=$_.name -Replace $regex
Rename-Item -path $_.Fullname -newname $New -passthru
}
I'm not very versed in Powershell yet and would love some help with this. I just want the script that, if it finds a duplicate, it should just add a (1) or (2) etc at the end, depending on how many there are.
Please don't just give me an answer, explain it so that I can learn what is happening
I think the way to tackle this is to create a new PSOBJECT which contains your source and target paths. You can then use the Group-object to group on the target path which will give you a count which you can then use to determine which files will need a number suffix.
Something like this:
Get-ChildItem -recurse "D:\projects\filenameCleaner\TEST" | ? {!$_.PsIscontainer} | % {
New-Object psobject -Property #{
source = $_.FullName
target = ($_.FullName -replace [regex]::Escape($_.Name)) + ($_.Name -replace '[\$#]+', '')
}
} | Group-Object target | % {
$g = $_.Group
0..($g.Count - 1) | % {
New-Object psobject -Property #{
source = $g[$_].source
target = $g[$_].target -replace '\.', #('.', "($($_)).")[$_ -gt 0]
}
}
} | % {Rename-Item -Path $_.source -NewName $_.Target}
The nice thing about doing it this way is that it can two, three or more duplcates
I have only done the code for files so you would need another version for folders.
I was able to do this by adding an if-statement that checks the new path
$characters = "$#}"
$regex = "[$([regex]::Escape($characters))]"
$path = "D:\projects\filenameCleaner\TEST"
$filesandfolders = Get-ChildItem -recurse $path | Where-Object {$_.name -match $regex}
$filesandfolders | Where-Object {!$_.PsIscontainer} | foreach {
$New=$_.name -Replace $regex
$newPath = $path+"\"+$New
$loop = 0
while (Test-Path $newPath) {
$loop = $loop + 1
$basename = $_.basename -Replace $regex
$New = $basename + " ("+$loop+")"+$_.extension
$newPath = $path+"\"+$New
}
"Rename `""+$_.name+"`" to `""+$New+"`""
Rename-Item -path $_.Fullname -newname $New -passthru
}
$filesandfolders | Where-Object {$_.PsIscontainer} | foreach {
$New=$_.name -Replace $regex
$newPath = $path+"\"+$New
$loop = 0
while (Test-Path $newPath) {
$loop = $loop + 1
$basename = $_.basename -Replace $regex
$New = $basename + " ("+$loop+")"+$_.extension
$newPath = $path+"\"+$New
}
"Rename `""+$_.name+"`" to `""+$New+"`""
Rename-Item -path $_.Fullname -newname $New -passthru
}
-- Another update that handles the extensions separately when adding the number to the string for duplicates. I was having issues that the number would go onto the file name after the extension which is obviously a no-go

Recursively removing/renaming files using powershell

I have to go through many levels of child folders and remove special characters that are invalid in SharePoint, mainly '#&'
I have scoured the internet trying different commands; rename-item/move-item, variations of the two, all to no avail. The closest i've gotten is using:
Get-ChildItem -Recurse | Rename-Item -NewName {$_.Name -replace'[!##&]','_'}
but i keep getting this error: Rename-item: Source and destination path must be different.
Could someone point me in the right direction?
Regards
That error only happens when you attempt to rename a directory to the same NewName as the current name, you can safely ignore it.
Add -ErrorAction SilentlyContinue to silently suppress the error message:
Get-ChildItem -Recurse | Rename-Item -NewName {$_.Name -replace'[!##&]','_'} -ErrorAction SilentlyContinue
You need to filter out the files that you're not planning to rename:
Get-ChildItem -Recurse |
Where-Object { $_.Name -match '[!##&]' } |
Rename-Item -NewName {$_.Name -replace '[!##&]','_'}
something like this may work
dir -Recurse -File | ? basename -Match '[!##&]' | % {
# if the file.txt already exists, rename it to file-1.txt and so on
$num = 1
$base = $_.basename -replace'[!##&]', '_'
$ext = $_.extension
$destdir = Split-Path $_.FullName
$newname = Join-Path $destdir "$base$ext"
while (Test-Path $newname) {
$newname = Join-Path $destdir "$base-$num$ext"
$num++
}
ren $_.fullname $newname
}

Renaming a file that has a bracket in the file name using power shell

I am trying to rename a file that has a bracket in the file name. This does not seem to work because powershell sees [] as special characters and does not know what to do.
I have a folder on my computer c:\test. I want to be able to look through that folder and rename all files or portions of the file. The following code seems to work but if the file has any special characters in it the code fails:
Function RenameFiles($FilesToRename,$OldName,$NewName){
$FileListArray = #()
Foreach($file in Get-ChildItem $FilesToRename -Force -Recurse | Where-Object {$_.attributes -notlike "Directory"})
{
$FileListArray += ,#($file)
}
Foreach($File in $FileListArray)
{
IF ($File -match $OldName )
{
$File | rename-item -newName {$_ -replace "$OldName", "$NewName" }
}
}
}
renamefiles -FilesToRename "c:\test" -OldName "testt2bt" -NewName "test"
I did find a similar question: Replace square bracket using Powershell, but I can't understand how to use the answer cause it's just a link explaining the bug:
For multiple files this can be done with one line.
To remove the bracket you should try:
get-childitem | ForEach-Object { Move-Item -LiteralPath $_.name $_.name.Replace("[","")}
Move-Item -literalpath "D:\[Copy].log" -destination "D:\WithoutBracket.txt"
Use the literalpath switch with the Move-Item cmdlet [instead of using the rename-item cmdlet]
As far as bracket are concerned, you've got Microsoft official answer in an old Technet Windows PowerShell Tip of the Week.
You can use :
Get-ChildItem 'c:\test\``[*``].*'
Thanks for help guys you all helped a lot this is the solution I came up with in the end after reading your reply’s .
I have a folder on my pc called c:\test and it has a file in it called "[abc] testfile [xas].txt" and i want it to be called testfile2.txt
Function RenameFiles($FilesToRename,$OldName,$NewName){
$FileListArray = #()
Foreach($file in Get-ChildItem $FilesToRename -Force -Recurse | Where-Object {$_.attributes -notlike "Directory"})
{
$FileListArray += ,#($file.name,$file.fullname)
}
Foreach($File in $FileListArray)
{
IF ($File -match $OldName )
{
$FileName = $File[0]
$FilePath = $File[1]
$SName = $File[0] -replace "[^\w\.#-]", " "
$SName = $SName -creplace '(?m)(?:[ \t]*(\.)|^[ \t]+)[ \t]*', '$1'
$NewDestination = $FilePath.Substring(0,$FilePath.Length -$FileName.Length)
$NewNameDestination = "$NewDestination$SName"
$NewNameDestination | Write-Host
Move-Item -LiteralPath $file[1] -Destination $NewNameDestination
$NewNameDestination | rename-item -newName {$_ -replace "$OldName", "$NewName" }
}
}
}
renamefiles -FilesToRename "c:\test" -OldName "testfile" -NewName "testfile2"