I have a PowerShell script that writes some results into a file.
Remove-Item
.You can fulfill all the requirements above with rm -f
in Unix-like systems.
First I have tried Remove-Item -Force
, but it couldn't ignore nonexistent files (cf. rm -f
ignores nonexistent files).
PS C:\tmp> Remove-Item C:\tmp\foo.txt -Force
Remove-Item : Cannot find path 'C:\tmp\foo.txt' because it does not exist.
At line:1 char:1
+ Remove-Item C:\tmp\foo.txt -Force
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\tmp\foo.txt:String) [Remove-Item], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.RemoveItemCommand
Next, I have tried Remove-Item -ErrorAction Ignore
and Remove-Item -ErrorAction SilentlyContinue
, but they don't show error messages when they failed to remove the file (cf. rm -f
shows an error message like rm: cannot remove 'foo.txt': Operation not permitted
in this situation).
PS C:\tmp> $file = [System.IO.File]::Open('C:\tmp\foo.txt',[System.IO.FileMode]::Open,[System.IO.FileAccess]::Read,[System.IO.FileShare]::None)
PS C:\tmp> Remove-Item C:\tmp\foo.txt -ErrorAction Ignore
# I expected it shows an error because it couldn't remove the file because of the lock, but it showed nothing
PS C:\tmp> $file = [System.IO.File]::Open('C:\tmp\foo.txt',[System.IO.FileMode]::Open,[System.IO.FileAccess]::Read,[System.IO.FileShare]::None)
PS C:\tmp> Remove-Item C:\tmp\foo.txt -ErrorAction SilentlyContinue
# I expected it shows an error because it couldn't remove the file because of the lock, but it showed nothing
Is there rm -f
equivalent in PowerShell that fulfills all the requirements above?
If there are special commands you want to ignore you can use -erroraction 'silentlycontinue' which will basically ignore all error messages generated by that command. You can also use the Ignore value (in PowerShell 3+): Unlike SilentlyContinue, Ignore does not add the error message to the $Error automatic variable.
In PowerShell, rm is aliased to Remove-Item , but it doesn't accept -rf .
-ErrorAction:SilentlyContinue suppresses the error message and continues executing the command. -ErrorAction:Stop displays the error message and stops executing the command.
Every object in PowerShell has a Delete() method and you can use it to remove that object. To delete files and folders, use the Get-ChildItem command and use the Delete() method on the output. Here, this command will delete a file called “testdata. txt”.
To me, the simplest solution is:
if (test-path $file) {
remove-item $file
}
This also occurs to me. $error[0] is always the most recent error.
remove-item $file -erroraction silentlycontinue
if ($error[0] -notmatch 'does not exist') {
write-error $error[0] # to standard error
}
I think you can also use try/catch with specific exceptions. Here's an example. I found the exception through tab completion. But the script will stop with other uncaught exceptions. This error doesn't normally stop.
try { remove-item foo -erroraction stop }
catch [System.Management.Automation.ItemNotFoundException] { $null }
'hi'
You cannot do this with that cmdlet by itself. You have to provide additional logic for errors.
'D:\temp\abc.txt', 'D:\Temp\hw.txt', 'D:\Temp\nonexistent.txt.', 'D:\Temp\book1.csv' |
ForEach{
try {Remove-Item -Path $PSitem -WhatIf -ErrorAction Stop}
catch {Write-Warning -Message $PSItem.Exception.Message}
}
# Results
<#
What if: Performing the operation "Remove File" on target "D:\temp\abc.txt".
What if: Performing the operation "Remove File" on target "D:\Temp\hw.txt".
WARNING: Cannot find path 'D:\Temp\nonexistent.txt.' because it does not exist.
What if: Performing the operation "Remove File" on target "D:\Temp\book1.csv".
#>
You should leverage error handling in all your code (interactive and scripts). You can send any screen output to $null, Out-Null, or [void] to prevent it from going to the screen, but still, know that it happened.
For the use case you are asking for, you will need multiple logic (try/catch, if/then) statements.
So, something like this modified wrapper function:
function Remove-ItemNotFileLocked
{
[cmdletbinding(SupportsShouldProcess)]
[Alias('rinf')]
param
(
[parameter(Mandatory = $true)][string]$FullFilePath
)
$TargetFile = New-Object System.IO.FileInfo $FullFilePath
if ((Test-Path -Path $FullFilePath) -eq $false) {return $false}
try
{
$TargetFileStream = $TargetFile.Open([System.IO.FileMode]::Open, [System.IO.FileAccess]::ReadWrite, [System.IO.FileShare]::None)
if ($TargetFileStream)
{
$TargetFileStream.Close()
Remove-Item -Path $FullFilePath
}
$false
}
catch
{
$true
}
}
'D:\temp\abc.txt', 'D:\Documents\Return To Sender.docx','D:\Temp\nonexistent.txt.' |
ForEach {Remove-ItemNotFileLocked -FullFilePath $PSItem -WhatIf}
# Results
<#
What if: Performing the operation "Remove File" on target "D:\temp\abc.txt".
True
False
#>
Point of note: Text editors like notepad, etc. do not place locks on files.
If I don't want that screen noise, then... Comment out those $false and $True statements, they are there for debugging and validation efforts.
'D:\temp\abc.txt', 'D:\Documents\Return To Sender.docx','D:\Temp\nonexistent.txt.' |
ForEach {$null = Remove-ItemNotFileLocked -FullFilePath $PSItem -WhatIf}
# Results
<#
What if: Performing the operation "Remove File" on target "D:\temp\abc.txt".
#>
Of course, remove/comment out the -WhatIf to allow things to happen, and that noise goes away as well.
If you do not want to use a function, then this code block should solve your use case.
# Remove non-Locked file and show screen output
'D:\temp\abc.txt', 'D:\Documents\Return To Sender.docx','D:\Temp\nonexistent.txt.' |
ForEach{
try
{
$TargetFile = (New-Object System.IO.FileInfo $PSitem).Open(
[System.IO.FileMode]::Open,
[System.IO.FileAccess]::ReadWrite,
[System.IO.FileShare]::None
)
$TargetFile.Close()
Remove-Item -Path $PSItem -WhatIf
}
catch [System.Management.Automation.ItemNotFoundException]{$PSItem.Exception.Message}
catch {$PSItem.Exception.Message}
}
# Results
<#
What if: Performing the operation "Remove File" on target "D:\temp\abc.txt".
Exception calling "Open" with "3" argument(s): "The process cannot access the file 'D:\Documents\Return To Sender.docx' because it is being used by another process."
Exception calling "Open" with "3" argument(s): "Could not find file 'D:\Temp\nonexistent.txt'."
#>
# Remove non-Locked file and silence screen output
'D:\temp\abc.txt', 'D:\Documents\Return To Sender.docx','D:\Temp\nonexistent.txt.' |
ForEach{
try
{
$TargetFile = (New-Object System.IO.FileInfo $PSitem).Open(
[System.IO.FileMode]::Open,
[System.IO.FileAccess]::ReadWrite,
[System.IO.FileShare]::None
)
$TargetFile.Close()
Remove-Item -Path $PSItem -WhatIf
}
catch [System.Management.Automation.ItemNotFoundException]{$null = $PSItem.Exception.Message}
catch {$null = $PSItem.Exception.Message}
}
# Results
<#
What if: Performing the operation "Remove File" on target "D:\temp\abc.txt".
#>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With