I have this working, but need LastWriteTime
and can't get it.
Get-ChildItem -Recurse | Select-String -Pattern "CYCLE" | Select-Object Path, Line, LastWriteTime
I get an empty column and zero Date-Time data
CodePudding user response:
LastWriteTime
is a property of System.IO.FileSystemInfo, which is the base type of the items Get-ChildItem
returns for the Filesystem
provider (which is System.IO.FileInfo for files). Path
and Line
are properties of Microsoft.PowerShell.Commands.MatchInfo
, which contains information about the match, not the file you passed in. Select-Object
operates on the information piped into it, which comes from the previous expression in the pipeline, your Select-String
in this case.
You can't do this as a (well-written) one-liner if you want the file name, line match, and the last write time of the actual file to be returned. I recommend using an intermediary PSCustomObject
for this and we can loop over the found files and matches individually:
# Use -File to only get file objects
$foundMatchesInFiles = Get-ChildItem -Recurse -File | ForEach-Object {
# Assign $PSItem/$_ to $file since we will need it in the second loop
$file = $_
# Run Select-String on each found file
$file | Select-String -Pattern CYCLE | ForEach-Object {
[PSCustomObject]@{
Path = $_.Path
Line = $_.Line
FileLastWriteTime = $file.LastWriteTime
}
}
}
Note: I used a slightly altered name of
FileLastWriteTime
to exemplify that this comes from the returned file and not the match provided bySelect-String
, but you could useLastWriteTime
if you wish to retain the original property name.
Now $foundMatchesInFiles
will be a collection of files which have CYCLE
occurring within them, the path of the file itself (as returned by Select-String
), and the last write time of the file itself as was returned by the initial Get-ChildItem
.
Technically speaking you could also get fancy with Select-Object
and computed properties on the initial Get-ChildItem
but IMO the above is a more readable and maintainable approach.
CodePudding user response:
Select-String
's output objects, which are of type Microsoft.PowerShell.Commands.MatchInfo
, only contain the input file path (string), no other metadata such as LastWriteTime
.
To obtain it, use a calculated property, combined with the common -PipelineVariable
parameter,
which allows you to reference the input file at hand in the calculated property's expression script block as a System.IO.FileInfo
instance as output by Get-ChildItem
, whose .LastWriteTime
property value you can return:
Get-ChildItem -File -Recurse -PipelineVariable file |
Select-String -Pattern "CYCLE" |
Select-Object Path,
Line,
@{
Name='LastWriteTime';
Expression={ $file.LastWriteTime }
}
Note how the pipeline variable, $file
, must be passed without the leading $
(i.e. as file
) as the -PipelineVariable
argument . -PipelineVariable
can be abbreviated to -pv
.