Sunday, July 20, 2008

The Trouble with Piping

Update:  I was wrong, and I'm really happy about it.

Powershell piping works slightly different than I thought.  As each result is returned it is passed down the pipe, rather than waiting for the entire section to complete.  My earlier tests didn't show what I thought they did, and that was my mistake.  

The function I came up with for shortcircuiting on a recursive file search when a matching file is found at the bottom of this poast, but here is another way to do the same thing based on the rest of the the thread that is much simpler.

Note:  there is one last caveat to watch out for:  if you put parentheses around some code, that code will be executed in its entirety in order to evaluate it before continuing, so keep that in mind when piping commands if you are planning on short-circuiting the process early, as in these examples.

# Find-File($path, $fileglob)
# Returns the first file that matches the fileglob.
# Args:
#   $path: [string] The path to the directory to start 
#     searching under
#   $fileglob: [string] The filename pattern to match 
#     (same format as dir)
#
# Returns:
#   The file object of the first matching file.

# New Version
function First-File([string]$path, [string]$fileglob){ 
    dir $path -include $fileglob -r | foreach {Write-Output $_; continue}
}

# Old Version
function Find-File ([string]$path, [string]$filename) { 
  $files = @(dir $path) 

  foreach ($file in $files) { 
    if (-not ($file.Mode -match '^d') -and ($file.Name -like "$filename")) { 
      return $file 
    } 
  } 

  foreach ($file in $files) { 
    if ($file.Mode -match '^d') { 
      $result = (Get-File $file.FullName $filename) 

      if ($result) { 
        return $result 
      } 
    } 
  }
}

No comments: