Trying to use select-string
on a directory results in an error:
PS C:\> select-string pattern P:\ath\to\directory
select-string : The file P:\ath\to\directory cannot be read: Access to the path 'P:\ath\to\directory' is denied.
However, when I use get-childItem -recurse
, the command finishes without problem:
PS C:\> get-childItem -recurse P:\ath\to | select-string pattern
This sursprises me because get-childItem recurse
also passes directories down the pipeline. So, I'd have assumed that select-string
raises the same error when it processes the first directory.
Since this is not the case, I wonder where or how the directory is filtered out in the pipeline.
TL;DR: object magic.
When Get-Childitem
is run, it will return a collection of objects. This is passed to Select-String
. The cmdlet's source is available on Github. There's a ProcessRecord()
method that, well, processes input objects. It contains a few checks for object type and if those are directories. Like so,
if (_inputObject.BaseObject is FileInfo fileInfo)
...
if (expandedPathsMaybeDirectory && Directory.Exists(filename))
...
Thus, it doesn't matter that Get-Child
's collection contains both DirectoryInfo
and FileInfo
objects; the cmdlet is smart enough to figure out what it's trying to consume.