Reputation: 40499
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.
Upvotes: 2
Views: 488
Reputation: 24071
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.
Upvotes: 1
Reputation: 13451
The -Path
parameter of Select-String
expects paths to files:
-Path
Specifies the path to the files to search. Wildcards are permitted. The default location is the local directory.
Specify files in the directory, such as log1.txt, *.doc, or .. If you specify only a directory, the command fails.
That's why you get an error, when you pass a path to a directory to the -Path
parameter.
When you pipe objects to Select-String
, they do not necessarily need a Path
attribute that can be mapped to -Path
of Select-String
:
You can pipe any object that has a ToString method to
Select-String
.
So you can also pipe raw strings to Select-String
:
'test' | Select-String -Pattern 'test'
This line will return test
.
Get-ChildItem
returns objects of type System.IO.FileInfo
or System.IO.DirectoryInfo
. Select-String
will use the Path
attribute of System.IO.FileInfo
to parse the content of the file and it will use the string representation of System.IO.DirectoryInfo
to parse exactly this string representation (the path itsself). That's why you don't get errors in your pipeline.
New-Item -Name 'test' -Type Directory | Select-String -Pattern 'test'
This line will return the path to the just created directory test
.
Upvotes: 1