How do I remove Blank Space from File Names - powershell

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.

Related

Rename files with Powershell, file name already exist

I try to rename in batch files in multiple folders by removing - .extension
Example files:
test file 1 - 1234.docx
test file 1 - 4321.docx
test file 1 - 6789.docx
For this I run the following script:
Get-ChildItem -recurse -exclude .dxl | foreach {
Rename-Item -Path $_.FullName -NewName (($_.BaseName -replace '(.)-.*?$','$1') + $_.Extension) }
This will give me the following error:
"Rename-Item : Cannot create a file when that file already exists."
How can I get rid of this by adding (1), (2), (3) if the file already exist after renaming?
Here is something I came up with for this problem:
$FileTracker = #{}
$files = (Get-ChildItem -recurse -exclude "*.dxl" -file | sort fullname).fullname
$files | foreach {
$Base = (($_ | select-string -pattern "(.*)-.*?$").matches.groups[1].value).Trim()
if ($FileTracker[$Base]) {
Rename-Item -path $_ -newName ((split-Path $Base -Leaf),"($($FileTracker[$Base]))",($_ -replace ".*(\..*?)$",'$1') -join "")
$FileTracker[$Base]++
}
else {
$FileTracker.add($Base,1)
Rename-Item -path $_ -newName ((split-path $Base -Leaf),($_ -replace ".*(\..*?)$",'$1') -join "")
}
}
Keep in mind that this solution looks to make files unique in their respective directories. If it sees test file 1 - 23.txt in two different directories, it will rename them both to test file 1.txt. If you already have files that have been renamed like testfile 1(1).txt and testfile 1(2).txt, there will be issues with this working. So I need to know if that is a condition.

PowerShell bulk replacing a specific character and rename file extension

I need to bulk rename files in a file share that
contain a specific character, namely a tilde ~ and
have the file extension in capital letters or none at all.
The goal would be to replace the tilde with a simple -, keep the file extension, if there is one, but transform it into lowercase letters.
I've had success with the first part of the script that finds the files
$PATH = "\\<Fileservername>\<Folder>\"
$pattern = "*~*"
Get-ChildItem $PATH -Recurse | where {$_.Name -like $pattern}
What I'm struggling with is the second part of the script the renaming.
I've found two topics here:
Powershell renaming a specific Character
PowerShell Regex Bulk Replace Filenames
I haven't been able to adapt those solutions to my need plus there may be additional steps to take in order to convert the given file name from capital letters to lowercase letters or skip this if the file has no file extension.
An example would be to rename ACUJLH~H to ACUJLH-H and KYA3BM~Q.PDF to KYA3BM-Q.pdf.
Here's my contribution. I have added the -File switch to the Get-ChildItem cmdlet so it will look for files only and will not try and handle directory names.
Also, I have changed the replace pattern to ~+ so files that have repeating tildes will be replaced with a single - character. (KYA3BM~~~~Q.PDF becomes KYA3BM-Q.pdf)
$path = "D:\Code\PowerShell\StackOverflow"
$pattern = "*~*"
Get-ChildItem $path -Recurse -File | Where-Object {$_.Name -like $pattern} |
ForEach-Object {
$directory = $_.DirectoryName # or [System.IO.Path]::GetDirectoryName($_.FullName) or use Split-Path $_.FullName -Parent
$filename = $_.BaseName -replace '~+', '-' # or [System.IO.Path]::GetFileNameWithoutExtension($_.Name) -replace '~+', '-'
$extension = $_.Extension # or [System.IO.Path]::GetExtension($_.Name)
if (![string]::IsNullOrEmpty($extension)) { $filename += $extension.ToLower() }
$newname = Join-Path -Path $directory -ChildPath $filename
Rename-Item -LiteralPath $_.FullName -NewName $newName -Force
}
You will need to filter files those meets your criteria. Then using ForEach-Object compare for extensions and build new file names for every found item. Finally, using Rename-Item cmdlet you make the change.
$PATH = '\\<Fileservername>\<Folder>\'
Get-ChildItem $PATH -Recurse -Include '*~*' | ForEach-Object {
[String]$Extension = [System.IO.Path]::GetExtension($_)
[String]$NewFileName = [System.IO.Path]::GetFileNameWithoutExtension($_.Name) -replace '~','-'
if ($Extension){ $NewFileName += $Extension.ToLower() }
Rename-Item $_.FullName $(Join-Path ([System.IO.Path]::GetDirectoryName($_)) $NewFileName) -Force
}

Rename all sub elements with incremental number

I'm new in powershell, I have to execute the following statement recursively:
Get-ChildItem | ForEach-Object {Rename-Item $_ -NewName ("new_filename{0}.smali" -f $nr++)}
In other words I have to rename all the .smali files in the subdirectories with any other name different from the current one (keeping the .smali extension).
Get-ChildItem -Path FolderPath -Filter *.smali -Recurse | ForEach-Object{$_ | Rename-Item -NewName ($.BaseName + StringToAdd + $.Extension) -WhatIf}
Copy the above line as is... Replace the values for FolderPath and StringToAdd and give it a try. If everything looks fine then execute it by removing the -Whatif switch.
dir is an alias for Get-ChildItem which has a -Recursive parameter.
$nr = 0; Get-ChildItem -Recurse -Filter "*.smali" | Rename-Item -NewName "new_filename$($nr++).smali"
Things to note:
DIR is an alias for Get-ChildItem. Get-ChildItem is more Powershell-y
Your command only looked at the top level directory, so I added the -recurse
Your command would rename all files, not just the "*.smali", so I added the filter.

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.

error from Powershell when try to rename with sequential prefix *recursively*

I have no problem adding sequential prefixes to filenames. The following works great on the top directory in question.
$path="E:\path\newtest1"
$count=4000
Get-ChildItem $path -recurse | Where-Object {!$_.PSIsContainer -and $_.Name -NotMatch '^\d{4}\s+'} | ForEach -Process {Rename-Item $_ -NewName ("$count " + $_.name -f $count++) -whatif}
BUT if there are files in subfolders within the top directory, these are all completely missed. Whatif reports that for any deeper file it "does not exist".
I have tried the following, based on looking at some pages on other recursion problems, but as you can probably guess I have no clue what it is doing. Whatif shows that it does at least pickup and rename all the files. But the following does it too much and makes multiple copies of each file with each number:
$path="E:\path\newtest1"
$count=4000
Get-ChildItem -recurse | ForEach-Object { Get-ChildItem $path | Rename-item -NewName ("$count " + $_.Basename -f $count++) -whatif}
Really keen to get some guidance on how to get the first of these two snippets to work to find all files in all subdirectories and rename them with sequential number prepended.
Try it like so:
Get-ChildItem $path -recurse -file | Where Name -NotMatch '^\d{4}\s+' |
Rename-Item -NewName {"{0} $($_.name)" -f $count++} -whatif
When you supply $_ as an argument (not a pipeline object), that gets assigned to the Path parameter which is of type string. PowerShell tries to convert that FileInfo object to a string but unfortunately the "ToString()" representation of files in nested folders is just the filename and not the full path. You can see this by executing:
Get-ChildItem $path -recurse -file | Where Name -NotMatch '^\d{4}\s+' | ForEach {"$_"}
The solution is either to A) pipe the object into Rename-Item or B) use the FullName property e.g. Rename-Item -LiteralPath $_.FullName ....