Replacing "." in Powershell without altering extension - powershell

Hi I'm using the following Powershell Script to clean up some filenames..
get-childitem -recurse -Include *.mp4 | foreach { rename-item $_ $_.Name.Replace(".", " ") }
In short, replacing "." with " ".. However this also removes the "." preceding the extension.. Is there way I can exclude the final "." so the extension isn't changed?

You need to separate the path, base file name and the extension. Fortunately, the objects returned by Get-ChildItem have them available to you.
This should work (linebreak for readability)
get-childitem -recurse -Include *.mp4 | ForEach-Object {
rename-item $_ -newname $(Join-Path -Path $_.DirectoryName -ChildPath "$($_.BaseName.Replace(".", " "))$_.Extension)") -WhatIf }
Remove -whatif once you've confirmed that it's going to do what you want.

Related

How do I recursively rename files in a directory with Powershell?

I have a powershell script which appends " - Confidential" to the end of files that don't already match the string "Confidential" within the filename. When running this script in the directory, it works. However, I need it to rename all the items within the subfolder too. How could I achieve this?
Get-ChildItem * -Exclude *Confidential* -Recurse |
ForEach {Rename-Item -NewName { $_.BaseName + " - Confidential" + $_.Extension }}
Thanks all for reading.
You're close, but there's a few problems:
Rename-Item is missing the original file, so let's add $_ to it. We could have also given it $_.FullName but I'm just passing the entire object to it.
Rename-Item is being given a script block with no input for -NewName because you've used curly braces ({}), so we change it to regular brackets (()).
Subfolders are also being renamed, which also results in files in them not being recursed (because they contain Confidential), so we specify the -File switch on Get-ChildItem to only return files.
So that brings us to this:
Get-ChildItem * -File -Exclude *Confidential* -Recurse |
ForEach {Rename-Item $_ -NewName ( $_.BaseName + " - Confidential" + $_.Extension )}
And just some cleanup/optimisation:
Remove wildcard (*) from Get-ChildItem. It already assumes all items in the folder you're in.
Enclose string in quote marks.
Add some spaces inside script block and change ForEach alias to shorter % alias (both just my personal preference).
And the final result looks like this:
Get-ChildItem -File -Exclude "*Confidential*" -Recurse |
% { Rename-Item $_ -NewName ( $_.BaseName + " - Confidential" + $_.Extension ) }
As always, you can do a dry run by specifying -WhatIf on Rename-Item, just in case there's some unexpected behaviour.
Edit: You could actually just pipe the output of Get-ChildItem into Rename-Item like so without the need for ForEach-Object:
Get-ChildItem -File -Exclude "*Confidential*" -Recurse |
Rename-Item -NewName { $_.BaseName + " - Confidential" + $_.Extension }

Skipping files with a given prefix when renaming

I have the following script for renaming a bunch of files in a directory, adding the name of the directory to the start of them:
$s = "Y:\Teknisk Arkiv\Likeretter 111-Å1\E2_Kretsskjema\02_Likeretter styring\3AJJ000302-222"
Get-ChildItem -Path $s -Exclude $_.Directory.Name* | rename-item -NewName { $_.Directory.Name + '_' + $_.Name }
Before running the script the files in the folder looks something like this
after like this
As you can see it does more or less what I want, except that -exclude $_.DirectoryName* doesn't prevent files which already have the foldername as a prefix from being renamed. What am I doing wrong here?
$_ in a pipeline is only defined inside a script block used in a non-initial pipeline segment, where it refers to the input object at hand, so in your Get-ChildItem command it is effectively undefined.
Even if $_.Directory.Name did have a value, $_.Directory.Name* wouldn't work as expected, because it would be passed as 2 arguments (you'd have to use "$($_.Directory.Name)*" or ($_.Directory.Name + '*').
You instead want to extract the directory name from the $s input path, which you can do with Split-Path -Leaf, and then append '*'.
In order for -Exclude to be effective, the input path must end in \*, because -Include and -Exclude filters - perhaps surprisingly - operate on the leaf component of the -Path argument, not on the child paths (unless -Recurse is also specified).
To put it all together:
Get-Item -Path $s\* -Exclude ((Split-Path -Leaf $s) + '*') |
Rename-Item -NewName { $_.Directory.Name + '_' + $_.Name }
I've switched to Get-Item, since \* is now being used to enumerate the children, but Get-ChildItem would work too.
The $_ is only valid when it is used on the right-side of a pipeline meaning when you have a collection of items and "pipe" them through the "$_" would represent the current item.
Since the directory name you want excluded is static you can just hardcode it and use as your exclude filter.
$s = "Y:\Teknisk Arkiv\Likeretter 111-Å1\E2_Kretsskjema\02_Likeretter styring\3AJJ000302-222"
$exclude_filter = "3AJJ000302-222*"
Get-ChildItem -Path $s -Exclude $exclude_filter | rename-item -NewName { $_.Directory.Name + '_' + $_.Name }
Also try to use "-whatif" with rename-item so you know what will happen before it happens.
$_ represents the currently processed item, what requires a ForEach-Object or a scriptblock inside a pipe, not present at the begin of your command.
Solution make the path a FileInfoObject and use -Exclude
$s = Get-Item "Y:\Teknisk Arkiv\Likeretter 111-Å1\E2_Kretsskjema\02_Likeretter styring\3AJJ000302-222"
Get-ChildItem -Path $s -Exclude "$($s.Name)*"|Rename-Item -NewName {$_.Directory.Name+'_'+$_.Name}
solution use a Where-Object to filter files already starting with the directory name
Get-ChildItem -Path $s | Where-Object {$_.Directory.Name -notlike "$($_.Name)*"} |
Rename-Item -NewName { $_.Directory.Name + '_' + $_.Name }
Solution use the RegEx based -replace operator to prepend the directory name and use a negative lookahead assertion to exclude files which already have it.
Get-ChildItem -Path $s |
Rename-Item -NewName {$x=$_.Directory.Name;$_.Name -replace "^(?!$x)",$x}

Cycle through sub-folders to rename files in Powershell

I have a file directory that contains many folders within it. Inside each of these sub-folders, I have a variety of files. I would like to go through each file, rename some of the items, and add extensions to some of them. I am using Powershell to do this.
I have file names with "." that all need to be replaced with "_" for example, "wrfprs_d02.03" should be "wrfprs_d02_03". I was able to successfully do that in one folder with the following code:
dir | rename-item -NewName {$_.name -replace "wrfprs_d02.","wrfprs_d02_"}
After, I make those replacements, I want to add .grb extensions on to some of the files, which all happen to start with "w", and I was able to do that within one folder with:
Get-ChildItem | Where-Object {$_.Name -match "^[w]"} | ren -new {$_.name + ".grb"}
When I step back from one folder and try to do it iteratively within many folders, my code doesn't work. I am in a directory called "Z:\Windows.Documents\My Documents\Test_data\extracted" which contains all my sub-folders that I want to iterate over. I am using the following code:
$fileDirectory = "Z:\Windows.Documents\My Documents\Test_data\extracted"
foreach($file in Get-ChildItem $fileDirectory)
{
dir | rename-item -NewName {$_.name -replace "wrfprs_d02.","wrfprs_d02_"}
Get-ChildItem | Where-Object {$_.Name -match "^[w]"} | ren -new {$_.name + ".grb"}
}
Any ideas on what my problem is?
because you $_ is replaced into loop when you use pipe. I propose you a new code:
$fileDirectory = "Z:\Windows.Documents\My Documents\Test_data\extracted"
Get-ChildItem $fileDirectory -recurse -file -filter "*.*" |
%{
#replace . by _
$NewName=$_.Name.Replace(".", "_")
#add extension grb if name start by w
if ($NewName -like "w*") {$NewName="$NewName.grb"}
#Add path file
$NewName=Join-Path -Path $_.directory -ChildPath $NewName
#$NewName
#rename
Rename-Item $_.FullName $NewName
}
Not sure what error you were getting, but using rename-item can be finicky. Or at least so in my experience.
I used the follow without issue. My files names were different so I replaced all periods with underscores. If the file starts with "W" then it changed the extension for that file.
$FilePath = Get-ChildItem "Z:\Windows.Documents\My Documents\Test_data\extracted" -Recurse -File
foreach ($file in $FilePath)
{
$newName = $file.Basename.replace(".","_")
$New = $newName + $file.Extension
if($file.Name -match "^[w]")
{
Rename-Item $file.FullName -NewName "$($New).grb"
}
else
{
Rename-Item $file.FullName -NewName $New
}
}
Hope that helps.

Rename-item in multiple subfolders

I have a piece of software which looks for a files named "report.txt". However, the text files aren't all named report.txt and I have hundreds of sub folders to go through.
Scenario:
J:\Logs
26-09-16\log.txt
27-09-16\report270916.txt
28-09-16\report902916.txt
I want to search through all the sub folders for the files *.txt in J:\logs and rename them to report.txt.
I tried this but it complained about the path:
Get-ChildItem * |
Where-Object { !$_.PSIsContainer } |
Rename-Item -NewName { $_.name -replace '_$.txt ','report.txt' }
Get-ChildItem * will get your current path, so in instead let's use the define the path you want Get-ChildItem -Path "J:\Logs" and add recurse because we want the files in all the subfolders.
Then let's add use the include and file parameter of Get-ChildItem rather than Where-Object
Then if we pipe that to ForEach, we can use the Rename-Item on each object, where the object to rename will be $_ and the NewName will be report.txt.
Get-ChildItem -Path "J:\Logs" -include "*.txt" -file -recurse | ForEach {Rename-Item -Path $_ -NewName "report.txt"}
We can trim this down a bit in one-liner fashion with a couple aliases and rely on position rather than listing each parameter
gci "J:\Logs" -include "*.txt" -file -recurse | % {ren $_ "report.txt"}
To replace certin word in all files in all sub folders
Get-ChildItem C:\Path -Recurse -Filter *OldWord* | Rename-Item -NewName { $_.name -replace 'OldWord', 'NewWord'} -verbose

How do I remove Blank Space from File Names

I am trying to remove blank spaces from many file names using PowerShell 3.0. Here is the code that I am working with:
$Files = Get-ChildItem -Path "C:\PowershellTests\With_Space"
Copy-Item $Files.FullName -Destination C:\PowershellTests\Without_Space
Set-Location -Path C:\PowershellTests\Without_Space
Get-ChildItem *.txt | Rename-Item -NewName { $_.Name -replace ' ','' }
For example: the With_Space directory has these files:
Cable Report 3413109.pdf
Control List 3.txt
Test Result Phase 2.doc
The Without_Space directory will need the above file name to be:
CableReport3413109.pdf
ControlList3.txt
TestResultPhase 2.doc
Currently, the script shows no error but it only copies the source files to the destination folder, but doesn't remove the spaces in file names.
Your code should work just fine, but since Get-ChildItem *.txt lists only .txt files the last statement should remove the spaces from just the text files, giving you a result like this:
Cable Report 3413109.pdf
ControlList3.txt
Test Result Phase 2.doc
This should remove spaces from the names of all files in the folder:
Get-ChildItem -File | Rename-Item -NewName { $_.Name -replace ' ','' }
Prior to PowerShell v3 use this to restrict processing to just files:
Get-ChildItem | Where-Object { -not $_.PSIsContainer } |
Rename-Item -NewName { $_.Name -replace ' ','' }
something like this could work
$source = 'C:\temp\new'
$dest = 'C:\temp\new1'
Get-ChildItem $source | % {copy $_.FullName $(join-path $dest ($_.name -replace ' '))}
I think your script should almost work, except $_ isn't going to be defined as anything. By using the for-each cmdlet (%), you assign it and then can use it.
Get-ChildItem *.txt | %{Rename-Item -NewName ( $_.Name -replace ' ','' )}
EDIT:
That interpretation was totally wrong. Some people seem to have found it useful, but as soon as you have something being piped, it appears that $_ references the object currently in the pipe. My bad.