I am dealing with the Windows bug where you are unable to delete Thumbs.db, as Windows thinks they are "open".
Firstly, I am aware of the possibility of using regedit to allow these to be deleted, but I do not own the network folder so am unable to access the server to do this. However if it helps anyone here is how you would do that:
add a new "Explorer" Registry path:
HKEY_CURRENT_USER\Software\Policies\Microsoft\Windows\Explorer\
and then add a DWORD entry called "DisableThumbsDBOnNetworkFolders", and set it to 1.
I have found that if I manually rename the Thumbs.db to say "ThisSucks.db" then I can delete the file. I have a ton of these folders with Thumbs in them so I want to write a PS script to rename all of them, or bonus delete.
When I gather the thumbs into a collection, I see the Write-Host print for each file, but when I try to rename I am getting "Cannot rename because file does not exist".
[System.Object[]] $directory = Get-ChildItem -Path $Path -Filter "*.db" -Force -Recurse;
foreach($file in $directory){
Write-Host -ForegroundColor Green "Found Thumb files";
Rename-Item $file "StupidFile.db";
}
Any ideas?
TessellatingHeckler provided the crucial pointer in a comment on the question:
Perhaps surprisingly, the [System.IO.FileInfo]
instances returned by Get-ChildItem
bind to Rename-Item
's -Path
parameter as strings when passed as direct argument, and, in a string context, a [System.IO.FileInfo]
instance expands to its mere filename, not the full path.
Therefore, unless a [System.IO.FileInfo]
instance happens to refer to a file in the current directory, Rename-Item
won't find it.
Binding the [System.IO.FileInfo]
instances via the pipeline is not subject to this pitfall (the .PSPath
property is used for binding to -Path
), so you can use the following:
Get-ChildItem -Path $Path -Filter '*.db' -Force -Recurse |
Rename-Item -NewName 'StupidFile.sb' -WhatIf
Note the -WhatIf
switch, which previews the renaming operations. Remove this switch to perform the actual renaming.
A note on your first statement, [System.Object[]] $directory = Get-ChildItem ...
:
Rather than casting to [System.Object[]]
, you can use @()
, the array subexpression operator, to ensure that a command's output is treated as an array, even if it returns only a single item (or none):
$directory = @(Get-ChildItem ...)
That said, on PSv3+ this is typically not necessary, because any scalar value can also be used as if it were an array; e.g.:
> $scalar = 'a single value'
# Treat $scalar as a collection:
# A scalar as a collection by definition has count 1.
> $scalar.Count
1
# Enumerate the scalar in a foreach loop.
> foreach ($itm in $scalar) { "[$itm]" }
[a single value]
# Process the scalar in a pipeline using the ForEach-Object cmdlet.
> $scalar | ForEach-Object { "[$_]" }
[a single value]