PowerShell Rename Item fail - powershell

i found out about Powershell renaming some years ago by trying to remove the "-eng" part at the end of .srt files for tv series.
Found this command which has been working perfectly when i needed to rename dozens of files.
get-childitem *.srt | foreach {rename-item $_ $_.name.replace("-eng","")}
This is the only command i know of. I just know nothing about powershell nor coding at all.
Now for example i have these files.
Sword Art Online II - 01 [BD][FS].mp4
Sword Art Online II - 02 [BD][FS].mp4
24 of them.
The idea is to get this result
02 - 01.mp4
02 - 02.mp4
etc.
So i need to replace.
Sword Art Online II --> 02
and
[BD][FS] --> ""
Thought it wouldnt be that hard. But im getting erros. For example i tried
get-childitem *.mp4 | foreach {rename-item $_ $_.name.replace("Sword Art Online II ","")}
But i get this error
rename-item : Cannot rename because item at 'C:\users\santo\downloads\02\Sword Art Online II - 01 [BD][FS].mp4' does
not exist.
At line:1 char:32
+ ... | foreach {rename-item $_ $_.name.replace("Sword Art Online II ","") ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Rename-Item], PSInvalidOperationException
+ FullyQualifiedErrorId : InvalidOperation,Microsoft.PowerShell.Commands.RenameItemCommand
So i tried with the last part but i get the exact same error
rename-item : Cannot rename because item at 'C:\users\santo\downloads\02\Sword Art Online II - 01 [BD][FS].mp4' does not exist.
At line:1 char:32
+ ... item *.mp4 | foreach {rename-item $_ $_.name.replace(" [BD][FS]","")}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Rename-Item], PSInvalidOperationException
+ FullyQualifiedErrorId : InvalidOperation,Microsoft.PowerShell.Commands.RenameItemCommand
I believe i am in the correct directory cause i enter dir command and it lists all 24 files by using "cd " and "cd.."
Using Windows Powershell (admin)
Tried looking for the error line. What does this mean " PSInvalidOperationException " I just dont know what im getting into.
What am i doing wrong? Any thoughts?

First of all, note that you don't necessarily have to be in the right directory. You can specify the path for Get-Childitem directly via the -Path (or -LiteralPath) parameter. (See the documentation.)
Also, Rename-Item expects a file name. If you pass $_, which is of type FileInfo, it will be implicitly converted to a string, resulting in only the file name, not the full path. This can lead to errors, if you're not in the right directory. You can use $_.FullName. Or even better, you can pipeline the results directly into the command.
Lastly, it looks like your -Filter is wrong. Shouldn't it be *.mp4?
Here's my updated version of the command. Let me know if it works or if you have any questions
Get-ChildItem -Path "C:\users\santo\downloads" -Filter *.mp4 |
Rename-Item -NewName {$_.Name.Replace("Sword Art Online II", "02").Replace(" [BD][FS]", "")}
Note: Always include the -WhatIf switch first, to check what the command will do, before you actually run it. This will help you troubleshoot and prevent you from making unwanted changes.
(It would look like this: ... | Rename-Item -WhatIf -NewName ...)
If you need help with any command, you can always use -? (e.g. Rename-Item -?) or use the Get-Help cmdlet, (e.g. Get-Help Rename-Item or Get-Help Rename-Item -Examples)

Don't use ForEach, directly pipe like this to Rename-Item:
dir "C:\users\santo\downloads" -filter *.mp4 |
ren -NewName {$_.Name.Replace('Sword Art Online II', '02').Replace(' [BD][FS]', '')}
If you still wanna use Foreach:
dir -filter *.mp4 |
% {ren $_.fullname -newname {$_.name.replace("Sword Art Online II ","").Replace(' [BD][FS]', '')}}

Related

Powershell script to rename Files adding Last Modified date to name, script won't run in sub directories

I have an old server archived and would like to rename all the files by adding the last modified date to the file name.
There are many layers of folders in the directory structure.
I have tried a few different versions of scripts and the first level works fine, then it errors on the sub folders.
Error:
Rename-Item : Cannot rename because item at 'Stand.doc' does not exist.
At line:1 char:42
+ ... ch-Object { Rename-Item $_ -NewName ("{0}-{1}{2}" -f $_.BaseName,$_.L ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Rename-Item], PSInvalidOperationException
+ FullyQualifiedErrorId : InvalidOperation,Microsoft.PowerShell.Commands.RenameItemCommand*
Stand.doc is a file from a sub directory.
Semi-Working script:
Get-ChildItem -recurse |Foreach-Object { Rename-Item $_ -NewName ("{0}-{1}{2}" -f $_.BaseName,$_.LastWriteTime.ToString('"Last_Mod_Date_"mmddyyyy'),$_.Extension) }
Thank you
I've been able to reproduce this with Windows PowerShell (5.1) after all but I cannot reproduce it in PowerShell Core 7.2.3. I'm not quite sure what the issue here is but this answer should only be considered relevant for PowerShell Core. I will try to revisit this later to see if I can't figure out what's going on with PowerShell 5.1.
You will want to use the -File parameter with Get-ChildItem. The following should work for you to only return nested files so you don't accidentally try renaming directories:
Get-ChildItem -Recurse -File | Foreach-Object {
Rename-Item -WhatIf $_ -NewName ( "{0}-{1}{2}" -f $_.BaseName, $_.LastWriteTime.ToString('"Last_Mod_Date_"mmddyyyy'), $_.Extension )
}
I've added a -WhatIf parameter to Rename-Item, once you confirm the correct file list will be renamed, you can remove this to actually have the rename operation work.

WindowsPowerShell Rename Item

When I attempt to rename a contracts folder to capitalize the contracts folder I'm receiving an error for renaming it. I've tried "rename-item contracts Contracts" as well. Anyone know if I can force the command or do i need to change my syntax?
PS C:\> rename-item -Path .\contracts\ -NewName .\Contracts\
rename-item : Cannot rename the specified target, because it represents a path or device name.
At line:1 char:1
+ rename-item -Path .\contracts\ -NewName .\Contracts\
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Rename-Item], PSArgumentException
+ FullyQualifiedErrorId : Argument,Microsoft.PowerShell.Commands.RenameItemCommand
Rename-Item is (and filenames in general in Windows are) not case sensitive.
You need to rename it to a temp file and then rename to desired name.
Two steps, as below,
Rename-Item -Path ".\contracts" -NewName ".\contracts_temp" -PassThru | Rename-Item -NewName ".\Contracts"
Abdullah Leghari's helpful answer provides an effective workaround, but it's worth stating that what you tried should work if you remove the trailing \ (and, optionally, the leading .\):
A trailing \ (or /) in the -NewName argument rightfully results in the error message you saw, because the -NewName argument by definition accepts a name only, not a path (however, a leading .\ by itself is quietly tolerated, even though it arguably shouldn't be either, for consistency).
However, in case-insensitive file systems (by default: Windows, macOS), it should be possible to rename a directory to a case variation of it, which currently only works with files.
See GitHub issue #14903.
In short:
Rename-Item -Path .\contracts\ -NewName Contracts
should work and, if the stated bug is fixed, will work in a future PowerShell (Core) version (but won't ever in Windows PowerShell, which will see no updates except critical bug fixes).
You need to remove the trailing "\" from the path parameter.
rename-item .\contracts .\Contracts
or
rename-item -Path .\contracts -NewName .\Contracts

Rename-item: Cannot rename because item at ... does not exist [duplicate]

This question already has an answer here:
batch renaming files using powershell
(1 answer)
Closed 2 years ago.
I am lost with simple rename-item. Need to change names of folders to "01", "02", "03"... Tried everything but at the end I get this "Item doesn't exist". Sorry for dumb question but I am looking for a solution all day.
PS C:\Users\admin>
$nr = 1
Dir E:"Data-test" | %{Rename-Item $_ -NewName (‘{0}’ -f $nr++)}
Rename-Item : Cannot rename because item at 'ert' does not exist.
At line:3 char:23
+ Dir E:"Data-test" | %{Rename-Item $_ -NewName (‘{0}’ -f $nr++)}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Rename-Item], PSInvalidOperationException
+ FullyQualifiedErrorId : InvalidOperation,Microsoft.PowerShell.Commands.RenameItemCommand
Rename-Item : Cannot rename because item at 'ukh' does not exist.
At line:3 char:23
+ Dir E:"Data-test" | %{Rename-Item $_ -NewName (‘{0}’ -f $nr++)}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Rename-Item], PSInvalidOperationException
+ FullyQualifiedErrorId : InvalidOperation,Microsoft.PowerShell.Commands.RenameItemCommand
Rename-Item : Cannot rename because item at 'yph' does not exist.
At line:3 char:23
+ Dir E:"Data-test" | %{Rename-Item $_ -NewName (‘{0}’ -f $nr++)}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Rename-Item], PSInvalidOperationException
+ FullyQualifiedErrorId : InvalidOperation,Microsoft.PowerShell.Commands.RenameItemCommand
user14915444's helpful answer has provided the crucial pointer:
The problem is that Windows PowerShell situationally stringifies Get-ChildItem (dir) output objects by file name rather than by full path, necessitating the use of $_.FullName rather than just $_; the problem has been fixed in PowerShell [Core] v6.1+ - see this answer for details.
However, in your case the problem can be avoided altogether, by piping the Get-ChildItem output directly to Rename-Item, using a delay-bind script block, which also speeds up the operation:
[ref] $nr = 1
Get-ChildItem E:Data-test | Rename-Item -NewName { '{0}' -f $nr.Value++ } -WhatIf
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.
Note the use of a [ref] variable, which enables incrementing the sequence number across input objects from inside the delay-bind script block. This is necessary, because delay-bind script blocks run in a child scope of the caller's scope - unlike the script blocks passed to ForEach-Object (%) and Where-Object (?).
See GitHub issue #7157 for a discussion of this discrepancy.
Your script works fine. (At least the first variation.) You can't run it but once because you rename the file it is working with (i.e. "Data-Test"). I just created a Data-Test file on my E: drive and ran your script without issue once. Then, on second attempt, it couldn't work because it worked the first time.
If you are working with the contents of a directory named "Data-Test," you need to append your $_ with .FullName. (EX: Rename-Item $_.FullName -NewName ...)
See image:
If it still doesn't work, ensure that you have a file/folder named "Data-Test" in the CWD of your E: drive. Placing a backslash in the location will guarantee you are working in the root. (EX: E:\Data-Test)

Adding .eml to the end of every filename in multiple folders

So here's the deal:
I been using Thunderbird - it been great but I want to move to Microsoft Outlook. Now because I taken things a little too far, I decided to use maildir for storing my emails. Again it was wonderful but I need to move on.
My plan was to do Thunderbird ->import into mailstore ->export to pst -> import into outlook (or get outlook to open the file).
Now that should be easy enough but the issue is that I need a way to add the ".eml" to the end of every file otherwise mailstore won't import the emails.
I'm running Windows 10 pro x64 and this is what I am doing in powershell:
Get-ChildItem -File -Recurse | % { Rename-Item -Path $_.PSPath -NewName $_.FullName ( $_.Name + ".eml" )}
Now I saw the answer given in https://stackoverflow.com/a/21611922/1129151 but it wasn't what I was after.
I also saw http://www.kevinberridge.com/2010/06/powershell-add-extension-to-every-file.html but the issue was that it didn't handle adding the ".eml" recursively.
When I tried to run the above code I get
Rename-Item : A positional parameter cannot be found that accepts
argument '1506493412587000.eml'. At line:1 char:36
+ ... curse | % { Rename-Item -Path $.PSPath -NewName $.FullName ( $_.Nam ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Rename-Item], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.RenameItemCommand
Could someone please tell me what I need to do to get the ".eml" on?
Thank you :)
So it seems that i have mislead you to the wrong help section, for that i'm sorry. I should have lead you to the help of rename-item. (sorry busy at work).
So there you would find:
get-childItem *.txt | rename-item -newname { $_.name -replace '\.txt$','.log' }
That should get you going, for example:
get-childItem C:\temp\pos\mail\*.* -Recurse | rename-item -newname { $_.name -replace '\.txt$','.eml' }
You should change the txt into the extension your files have.
Notice the \ and $ in the replace part?
That's a regular expression. The \ is to say, look for an actual dot.
The $-sign is to say, at the end of the string.
So all files have no extension.
I have added File parameter which will only retrieve files and not folder, use it if you have any sub folders in your mail folder.
get-childItem C:\temp\pos\mail\*.* -Recurse -File | rename-item -newname { "$($_.name).eml" }
You should have a look at the help of get-childitem.
Look at the examples and more in particular, example number 4.
EDIT:
Before you do this to all your files, have you done one manually and checked if it works in Outlook?

How to pipe a directory name into Remove-Item?

I'm not very savvy with powershell, so any help is appreciated.
I have a drive that holds users profiles. I need to remove a specific file from each user's profile. It's structured something like this. (Names changed to protect the innocent.)
E:\Profiles
UserID
Documents
OtherFolders
DirectoryToDeleteFrom
FileToDelete.txt
UserID2
...
...
I could use the following command to delete all of the files I need to get to, but it's unbearably slow as it's recursing through all of the other folders under UserID.
#this one would work perfectly, but is terribly slow
Get-ChildItem -Path E:\Profiles -Include FileToDelete.txt -Recurse
I know exactly where each file resides, so I thought that I could do this.
(Get-ChildItem -Path 'E:\Profiles' -Exclude *.lnk)|ForEach-Object{Remove-item -path 'E:\Profiles\' + $_.Name + '\Path\To\File\FileToDelete.txt'}
But I get the following error message:
Remove-Item : A positional parameter cannot be found that accepts
argument '+'. At line:1 char:70
+ (Get-ChildItem -Path 'E:\Profiles' -Exclude *.lnk)|ForEach-Object{Remove-item ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Remove-Item], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.RemoveItemCommand
I thought it was because I was passing Remove-Item a bad file path, but the following command generates the correct paths.
(Get-ChildItem -Path 'E:\Profiles' -Exclude *.lnk)|ForEach-Object{'E:\Profiles\' + $_.Name + '\Path\To\File\FileToDelete.txt'}
So what am I doing wrong here?
If you construct a string on the fly to be used inline, by another command, then put brackets around the path:
..{Remove-item -path ('E:\Profiles\' + $_.Name + '\Path\To\File\FileToDelete.txt')}