How to pipe a directory name into Remove-Item? - powershell

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

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.

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)

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

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

Powershell Remove-Item Cmdlet error

I'm using powershell to remove a directory with the command:
Remove-Item $pathAsString -Recurse -Force
However, it gives me the following error:
Remove-Item : Cannot remove the item at 'C:\Path' because it is in use.
At line:1 char:1
+ Remove-Item "C:\Path" -Recurse
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Remove-Item], PSInvalidOperationException
+ FullyQualifiedErrorId : InvalidOperation,Microsoft.PowerShell.Commands.RemoveItemCommand
I thought that was odd, because the directory shouldn't be in use. I can go into file explorer and delete the directory manually. I'm not really sure why this behavior is occurring. I'm fairly new to powershell, so don't understand exactly how it behaves.
My scripts interaction with the program includes:
Creating the folder
Downloading an MSI to the folder
Setting a variable to represent the MSI stored in the folder. Like so:
$MSIVariable = Get-ChildItem $Path | Where {&_.Name -eq "MSIName.msi"}
I'm assuming that something to do with the folder is within a stream of some sort, but don't know how I'd fix this issue.
EDIT:
Here is the code I use involving the folder:
Creating the Folder:
if(!(Test-Path $MSILocation))
{
New-Item $MSILocation -ItemType directory
}
Downloading the MSI:
$webClient = (New-Object System.Net.WebClient)
$downloadLocation = Join-Path $MSILocation $MSIName
$webClient.DownloadFile($downloadURL, $downloadLocation)