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

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?

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

PowerShell Rename Item fail

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]', '')}}

Powershell Move-Item from Import-CSV: Error - Could not find part of the path

I've been working on a script in Powershell to get paths from a CSV file and move those files at the corresponding path to a new destination elsewhere. often with a different filename.
I am using Version 5.0
For example:
Source Destination : C:\1\2\3\File.pdf, D:\3\7\8\9\FILE1.pdf
Now I used the following script and it was initially able to move some of the files:
Import-CSV "R:\MoveFiles.csv" -Delimiter "," -ErrorAction Stop | ForEach-Object{Move-Item -path $_.Source -Destination $_.Destination}
Although around half way through executing it started to return this error:
Move-Item : Could not find a part of the path. At line:1 char:238
+ ... Each-Object{Move-Item -Literalpath $.Source -Destination $.Destina ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : WriteError: (Q:\RECORDS\PRIV...-4-20_N1969.pdf:FileInfo) [Move-Item],
DirectoryNotFoundException
+ FullyQualifiedErrorId : MoveFileInfoItemIOError,Microsoft.PowerShell.Commands.MoveItemCommand
As far as I can tell there are no special characters that would prevent the path being found. If I replace Move-Item for Copy-Item it returns the same error. I have also checked the paths to see if they are true or not.
I am at my wits end with this. Not sure what else to try. I am after all a complete novice.
Thank you
NB: I worked out a solution to this issue. It would appear that the Move-Item cmdlet does not like creating directories.
Instead I made the directories first with New-Item -directories, getting the content from a text document where every line represented a path (no headers).
After creating empty directories first the original script worked as intended.
For anyone interested here is the directories script:
#CREATE DIRECTORIES FROM CSV
cd
$name = Get-Content ".\Create_New_Directories\Move_Directories_Test.txt"
Foreach ($_ in $name)
{
New-Item -Force -verbose -path $_ -Type Directory
}
Out-File ".\Create_New_Directories\Newoutput.txt"
Thank you everyone for your help.
To debug such cases, consider Move-Item's -WhatIf parameter. Like so,
... | ForEach-Object{Move-Item -whatif -path $_.Source -Destination $_.Destination}
This will print the intended operation, so you can double-check paths for any sheenigans.
What if: Performing the operation "Move File" on target "Item:
C:\Temp\SomeFile.xml Destination: C:\Temp\Somewhere\SomeFile.xml".
Not sure. But your error message indicates it's a write error of DirectoryNotFound.
So perhaps you should be making sure you have the perms on the target side and are not exceeding any character limits in the length of the path.
Some other things to consider/try:
Your CSV file should be in the format (the first line must be the headers):
Source,Destination
C:\1\2\3\SomeFile.pdf,D:\1\2\3\SomeFile.pdf
C:\1\2\3\SomeFile2.pdf,D:\1\2\3\SomeFile2.pdf
Also you are not santizing your input so if you made the CSV file in Excel you might have leading or trailing spaces. In that case either clean the file editing in Notepad or try $_.Source.trim() and $_.Destination.trim()
And like the other guy said the -whatif switch is useful and so is -verbose.
You might also try Move-Item -Force and/or opening powershell as an Administrator.
Good Luck! ;-)

Deleting log files that are buried with powershell

So I am trying to figure out a script to delete log files that are buried in many folders. Same path to the end folder minus the client name folder that changes. Below is an example of the code I thought would work which is failing horribly. Any advice would be appreciated.
gci X:\ -directory -recurse | ?{$_.FullName -match \\temp\\company\\.+?\\AppData\\logfiles -and $_.CreationTime -lt (get-date).AddDays(-20)}|Remove-Item -recurse -whatif
so the Directory is X and the path to the logfiles that I want to delete is temp\company\NAME\appdata\logfiles and the NAME folder is the one that could be one of any number of different clients names.
Error I keep getting.
At line:1 char:51
+ gci X:\ -directory -recurse | ?{$_.FullName -match \\temp\\company\\.+?\\ ...
+ ~
You must provide a value expression on the right-hand side of the '-match' operator.
At line:1 char:52
+ gci x:\ -directory -recurse | ?{$_.FullName -match \\Temp\\company\\.+?\\ ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Unexpected token '\\Temp\\company\\.+?\\AppData\\logfiles' in expression or statement.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : ExpectedValueExpression
Does anyone have any ideas what we are doing wrong or how to accomplish this goal?
Thanks in advance!
The errors are because second argument to -match needs to be in quotes.
But there may be a way to do this without needing the complexity of your example. Get-ChildItem can take both a -Path and a -Include (or -Filter) argument. So you might use something like this:
Get-ChildItem -path c:\xxx -Include *log.tmp -Recurse | ... | Remove-Item