Author Posts

September 27, 2014 at 6:27 am

Hello all,

I was hoping to find some help regarding a line of script I've written.

For my home situation, I've brewed together something that at one point, tries to delete some obsolete files (in this case .jpg files in my Music folder):

get-childitem D:\Music\*.jpg -recurse -force| foreach ($_) {remove-item $_.fullname; Add-Content $LogFile "`nDeleting file: $_"} 

For this, I also wanted the line to log exactly which files have been deleted with the part:

Add-Content $LogFile

This works just the fine. The variable LogFile contains all information I need, except for one thing....
Whenever a file can't be deleted (because for example lack of permissions), the log will still show "Deleting file: something.jpg".

Is it possible to also include the failed attempts at deleting a file, while still keeping the line as simple as possible?

Thanks in advance,

T.O.

September 27, 2014 at 11:59 am

You'd need to use some sort of error detection code. In this case, a try/catch would be most appropriate. If you want to keep it all crammed onto one line, it might look something like this:

Get-ChildItem D:\Music\*.jpg -recurse -force| ForEach-Object { $file = $_; try { Remove-Item $file.fullname -ErrorAction Stop; Add-Content $LogFile "`nDeleting file: $file" } catch { Add-Content $LogFile "`nError deleting file: $file, $_" } }

Personally, I would prefer to split this onto multiple lines to make it easier to read, though:

Get-ChildItem D:\Music\*.jpg -Recurse -Force |
ForEach-Object {
    $file = $_
    try {
        Remove-Item $file.fullname -ErrorAction Stop
        Add-Content $LogFile "`nDeleting file: $file"
    } catch {
        Add-Content $LogFile "`nError deleting file: $file, $_"
    }
}

September 27, 2014 at 12:07 pm

Is this what you're looking for?

Get-ChildItem D:\Music\*.jpg -Recurse -Force -File | % {
    try {
        Remove-Item -Path $_.fullname -Force -Confirm:$false -ErrorAction Stop
        "Deleted file: $($_.fullname)" | Out-File .\LogFile.txt -Append
    } catch {
        "Failed to delete file: $($_.fullname)" | Out-File .\LogFile.txt -Append        
    }
}

September 27, 2014 at 1:26 pm

There's a good "gotcha" to be aware of in that code, Sam. When you enter a catch block, the $_ variable is overwritten to contain the terminating error that was caught. That's why I saved the value of $_ as of the beginning of the ForEach-Object block into another variable called $file first, in my example.

September 27, 2014 at 3:12 pm

That's excellent to know Dave, thanks!

We can use pipeline variable also (PS V4) like:

Get-ChildItem D:\Music\*.jpg -Recurse -Force -File -PipelineVariable File | % {
    try {
        Remove-Item -Path $File.fullname -Force -Confirm:$false -ErrorAction Stop
        "Deleted file: $($File.fullname)" | Out-File .\LogFile.txt -Append
    } catch {
        "Failed to delete file: $($File.fullname)" | Out-File .\LogFile.txt -Append        
    }
}

September 28, 2014 at 10:17 am

Thank you for your replies!

Indeed the try/catch method is working perfectly. In the end, I've sacrificed my one-line wishes for a good working script.
Sam&Dave, thank you for your help with this.

Regards,

T.O.