Remove-Item doesn't work, Delete does - windows

Does anyone have any idea why Remove-Item would fail while Delete works?
In below script, I get a list of files I'd like to delete.
Using Remove-Item I get following error message:
VERBOSE: Performing the operation "Remove File" on target
"\\UncPath\Folder\test.rtf". Remove-Item : Cannot remove item
\\UncPath\Folder\test.rtf: Access to the path is denied.
but using Delete is deleting those files as we speak.
Script
$files = gci \\UncPath\Folder| ?{ $_.LastWriteTime -le (Get-Date).addDays(-28) }
# This doesn't work
$files | Remove-Item -force -verbose
# But this does
$files | % { $_.Delete() }

powershell may act strange with UNC path, I think it prepends the UNC Path with the current provider you can verify this with :
cd c:
test-path \\127.0.0.1\c$
returns TRUE
cd HKCU:
test-path \\127.0.0.1\c$
returns FALSE
when specifying the fullpath we're telling powershell to use the filesystem provider, that solves the problem. you could also specify the provider like remove-item filesystem::\\uncpath\folder

I can finally repro this and IMO it appears to be a bug. The repro is to have an open share like C$ but to set Deny Modify perms for the user on the file. When I do that, I observe this:
PS> gci '\\Keith-PC\C$\Users\Keith\foo.txt' | ri -for
ri : Cannot remove item \\Keith-PC\C$\Users\Keith\foo.txt: Access to the path is denied.
At line:1 char:43
+ gci '\\Keith-PC\C$\Users\Keith\foo.txt' | ri -for
+ ~~~~~~~
+ CategoryInfo : InvalidArgument: (\\Keith-PC\C$\Users\Keith\foo.txt:FileInfo) [Remove-Item], ArgumentExc
eption
+ FullyQualifiedErrorId : RemoveFileSystemItemArgumentError,Microsoft.PowerShell.Commands.RemoveItemCommand
PS> gci '\\Keith-PC\C$\Users\Keith\foo.txt' | %{$_.Delete()} # <== this works!
I also observe that removing the -Force parameter deletes the file without error as well. The deny perms still allow me to delete the file from Windows Explorer so that leads me to believe that the file should delete. So what is up with using the -Force parameter? When I delve into the ErrorRecord I see this:
Message : Access to the path is denied.
ParamName :
Data : {}
InnerException :
TargetSite : Void set_Attributes(System.IO.FileAttributes)
StackTrace : at System.IO.FileSystemInfo.set_Attributes(FileAttributes value)
at Microsoft.PowerShell.Commands.FileSystemProvider.RemoveFileSystemItem(FileSystemInfo
fileSystemInfo, Boolean force)
It seems that the -Force parameter is trying to set (more likely reset) attributes and the permissions on the file don't allow it e.g.:
PS> gci '\\Keith-PC\C$\Users\Keith\foo.txt' | %{$_.Attributes = 'Normal'}
Exception setting "Attributes": "Access to the path is denied."
At line:1 char:45
+ gci '\\Keith-PC\C$\Users\Keith\foo.txt' | %{$_.Attributes = 'Normal'}
+ ~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], SetValueInvocationException
+ FullyQualifiedErrorId : ExceptionWhenSetting
So it seems to me that PowerShell should first try as if the -Force weren't present and if that fails, then try resetting attributes.

Related

Remove-Item : Cannot remove item because it is being used by another process

The problem is very easy to understand.
Yesterday I have installed en_visual_studio_2015_shell_isolated_x86_dvd_9fda4a05.iso and the file is hanging on my Desktop.
When I try to delete it through Remove-Item .\en_visual_studio_2015_shell_isolated_x86_dvd_9fda4a05.iso the Terminal fires back with the error:
Remove-Item : Cannot remove item C:\Users\franc\OneDrive\Desktop\en_visual_studio_2015_shell_isolated_x86_dvd_9fda4a05.iso: The process cannot access the file
'C:\Users\franc\OneDrive\Desktop\en_visual_studio_2015_shell_isolated_x86_dvd_9fda4a05.iso' because it is being used by another process.
At line:1 char:1
+ Remove-Item .\en_visual_studio_2015_shell_isolated_x86_dvd_9fda4a05.i ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : WriteError: (C:\Users\franc\...vd_9fda4a05.iso:FileInfo) [Remove-Item], IOException
+ FullyQualifiedErrorId : RemoveFileSystemItemIOError,Microsoft.PowerShell.Commands.RemoveItemCommand
So I tried to find out what is handling that file:
$handleOut = handle
foreach ($line in $handleOut) {
if ($line -match '\S+\spid:') {
$exe = $line
}
elseif ($line -match 'C:\\Users\\franc\\OneDrive\\Desktop\\en_visual_studio_2015_shell_isolated_x86_dvd_9fda4a05.iso') {
"$exe - $line"
}
}
But the answer was:
System pid: 4 \<unable to open process> - 7540: File (R--) C:\Users\franc\OneDrive\Desktop\en_visual_studio_2015_shell_isolated_x86_dvd_9fda4a05.iso
System pid: 4 \<unable to open process> - 7B18: File (RW-) C:\Users\franc\OneDrive\Desktop\en_visual_studio_2015_shell_isolated_x86_dvd_9fda4a05.iso
I ultimately used Process Explorer and I found out that what is handling the file is OneDrive.
I stopped OneDrive but the problem persists.
Any suggestion?
This is sheerly speculation, but it sounds like you need to unmount the iso: https://www.digitalcitizen.life/mount-unmount-iso-file-explorer/
Have you tried running the command with the -Force parameter?
Remove-Item .\en_visual_studio_2015_shell_isolated_x86_dvd_9fda4a05.iso -Force

Rename certain characters from filenames in all files in a folder and his sub-folders

I Want to replace certain character from my files
for example
i want to change > "original" -> "something else"
i use this script to replace it in one folder only using powershell
Dir |>> Rename-Item -NewName { $_.Name -replace "original","something " }
the issue is , with that code , that's only replace the files inside one folder and it don't replace them in the subfolders
i need it to replace it in file on the folder and in the sub folder files too , is that possible?
( i'm kinda new to this )
note : this code shows this error when there's any subfolders with the files
erorr =
Rename-Item : Source and destination path must be different.
At line:2 char:1
+ Rename-Item -NewName { $_.Name -replace "original","something " }
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : WriteError: (F:\folder-name\...ff\py-compat:String) [Rename-Item], IOException
+ FullyQualifiedErrorId : RenameItemIOError,Microsoft.PowerShell.Commands.RenameItemCommand
Operating system : windows
info
Operating system model : windows 10
In case of directories the rename-item commandlet gets the same path as input and as value of the -newname parameter, so it errors out.
Adding the -verbose and -whatif switch parameters to the command will show that.
Use the -Path parameter to specify the base path you want to recurse, the -recurse switch parameter to recursively visit each subfolder, the -file switch parameter to filter out directories, and/or use the -filter parameter to include a subset of files.
Example:
get-childitem -Recurse -File -Path 'c:\temp' | rename-item -newname { $_.name -replace "original","replacement }

How to change date modified of C:\$RECYCLE.BIN?

Since you can only view the C:\$RECYCLE.BIN Folder when you uncheck (Hide protected Operating System Files) you can't change the date modified through the usual way with PowerShell:
$file = Get-Item C:\Path\TO\File.txt
$file.LastWriteTime = (Get-Date)
or
$folder = Get-Item C:\folder1
$folder.LastWriteTime = (Get-Date)
When calling Get-Item C:\$RECYCLE.BIN, I get the following error:
Get-Item : Cannot find path 'C:\.bin' because it does not exist.
At line:1 char:9
+ $file = Get-Item C:\$Recycle.bin
+ ~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\.bin:String) [Get-Item], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetItemCommand
How would I go about changing the date modified of it?
As C:\$RECYCLE.BIN contains $, PowerShell tries to evaluate the variable $RECYCLE, which is empty. Thus, the resulting path C:\.bin cannot be found. Quote your path with single quotes (') to prevent PowerShell from evaluating your string and also add the -Force parameter as it is a system directory:
Get-Item -Path 'C:\$RECYCLE.BIN' -Force
You can then access your files and change the LastWriteTime as you already tried in your question:
$fileObject = Get-Item -Path 'C:\$RECYCLE.BIN\S-1-5-21-3323847664-626704455-790384891-1001\$RT8USDF.txt' -Force
$fileObject.LastWriteTime = Get-Date

Cannot recursively remove certain files with Remove-Item -Recurse -Force

On powershell 5.1
Using this within a foreach loop, ex:
foreach ($i in $folder.subfolders) {
if( $i.path -like "*node_modules" ){
Remove-Item $i.path -Force -Recurse
}
}
I keep running into this particular error:
+ CategoryInfo : WriteError: (_node_modules_r...dationpath.html:FileInfo) [Remove-Item], DirectoryNotFoundException
+ FullyQualifiedErrorId : RemoveFileSystemItemIOError,Microsoft.PowerShell.Commands.RemoveItemCommand
Remove-Item : Cannot remove item C:\topDir\js\node_modules\ram
l-1-parser\documentation\interfaces\_node_modules_raml_definition_system_node_modules_raml_typesystem_dist_src_index_d_.numbertype.html:
Could not find a part of the path '_node_modules_raml_definition_system_node_modules_raml_typesystem_dist_src_index_d_.numbertype.html'.
At C:\topDir\re.ps1:12 char:11
+ Remove-Item $i.path -Force -Recurse
The files causing the error all exist and I've checked the path and as far as my eyes can tell, they're correct?
Only thing I can make out is that the filenames are abnormally long. But surely that can't be the cause of this?
Long UNC names are problematic to delete. This is a OS specific thing, that limit is 260 characters.
https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
On Windows 10 you can enable long path names, but that does not work in all situations. I some cases you have to result to using the short name, and this requires some conversion effort.
And ditto with what 'Beacon Bits' states, because there is no .subfolder property or method. You can see this by doing...
(gci D:\Temp) | Get-Member | Select Name,MemberType
If you are after the file in a parent or subfolder, you use the...
FullName Property
Something like...
(gci 'D:\Temp\*.txt' -Recurse).FullName
Results
D:\Temp\diff\TestFile_2.txt
...
D:\Temp\Duplicates\BeforeRename1\FsConfig.txt
...
D:\Temp\Duplicates\dup5\SomeRandomThing.txt
...

Metadata export error when running on large directory structures

This script exports the basic file metadata in PowerShell to a .csv.
PS K:\> Get-childitem -recurse -file | select-object length,lastwritetime,fullname | export-csv filelist.csv -notypeinformation
It works great on simple directory structures of 10-20K files, but when I run it on 500K+ files of complex, multi-level directory structures it freezes or gives me error:
At line:1 char:1
+ Get-childitem -recurse -file | select-object length,lastwritetime,ful ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (0:Int32) [], RuntimeException
+ FullyQualifiedErrorId : CallDepthOverflow
Is this a problem with the -recurse or else? Using PowerShell 5 1 (Major Minor).
Test to see how long the filepaths are.
If the filepaths are more than 248 characters... That may be why you are getting the error.
To check to see if any come back with more than 248 characters you can do
Get-childitem "filepath" -recurse | % {
$filepath = $_.FullName
$charactercount = ($filepath | Measure-Object -Character).Characters
If ($charactercount -gt 248){write-host $filepath}
}

Resources