midnightfm
midnightfm

Reputation: 328

ForEach with Try/Catch Error Handling

Here's my code so far:

$Folders = Get-ChildItem -Path U:\Powershell\Move-Files\Clients |
           ?{$_.PsIsContainer} |
           Select -ExpandProperty FullName

Get-ChildItem -Path U:\Powershell\Move-Files\Individual | ?{
    !($_.PsIsContainer)
} | %{
    #Part of the file to match
    $File = ($_.name.substring(0,$_.basename.length-11))
    $File = ($File -split '_')[1] + ", " + ($File -split '_')[0]
    # Find matching Directory
    $Path = $Folders | ?{$_ -match $File}

    Move-Item -Path $_.FullName -Destination $Path -ErrorAction Silently Continue

    Write-Host "Moved $_.FullName to $Path"
}

Basically, I have a lot of files named First_Last (MMM yyyy).pdf and this takes each file and creates a variable in the format of Last, First so that it can do a partial match and move the files to the destination folders (which are formatted Last, First ##-####). This all works fine, except I'm having trouble implementing try/catch error handling.

I replaced the line that starts with Move-Item with:

try {
  Move-Item -Path $_.FullName -Destination $Path -ErrorAction SilentlyContinue
  "Moved $_.FullName to $Path successfully" | Add-Content U:\Powershell\Move-Files\log.txt
} catch {
  "Error moving $_.FullName" | add-content U:\Powershell\Move-Files\log.txt
}

It works almost perfectly, except that the catch doesn't properly report which files are not being moved. The try part reads out fine in the log. But the catch will just read the following in the log:

Error moving Cannot process argument because the value of argument "destination" is null. Change the value of argument "destination" to a non-null value..FullName

Not sure how to fix it.

Upvotes: 0

Views: 3668

Answers (1)

Ansgar Wiechers
Ansgar Wiechers

Reputation: 200443

The current object ($_) in the catch block is the error/exception, not the current object from the operation that raised the exception. If you want to output the path in the error message you need to put it in a variable:

try {
  $file = $_.FullName
  Move-Item -Path $file -Destination $Path -ErrorAction SilentlyContinue
  "Moved $file to $Path successfully" | Add-Content 'U:\Powershell\Move-Files\log.txt'
} catch {
  "Error moving $file" | Add-Content 'U:\Powershell\Move-Files\log.txt'
}

As a side note: PowerShell does only simple variable expansion in strings. "$_.FullName" will be expanded to the string representation of $_ followed by the string ".FullName". If you want to expand a property of the current object you need either a subexpression:

"Error moving $($_.FullName)"

string concatenation:

"Error moving " + $_.FullName

or the format operator:

"Error moving {0}" -f $_.FullName

Upvotes: 5

Related Questions