I'm writing a script where I'm trying to output the results from a Get-ChildItem command to a log file. The script below is simplified to show the issue I'm having. For example, the WriteLog function is used several times in the actual Script. The file listing is not the only thing to be added to the log file.
The snippet below writes a long run-on line of all full filenames to the log.
$FilePath = "G:\Folder"
$LogPathName = "G:\Folder\TestLog.log"
Function WriteLog {
Param ([string]$LogString)
$Stamp = Get-Date
$LogMessage = "$Stamp - $LogString"
Add-Content $LogPathName -value $LogMessage
}
$FileList = Get-ChildItem –Path $FilePath -include ('*.csv', '*.xlsx')
writelog $FileList
I want each filename to begin on a new line--like a list. How can I do this?
CodePudding user response:
Leaving your function WriteLog
as is, the workaround is to iterate over each element of the array returned by Get-ChildItem
so that the function appends to the file line-by-line:
foreach($item in $FileList) {
WriteLog $item
}
However a more elegant way of approaching this would be to leverage ValueFromPipeline
, then you could simply pipe Get-ChildItem
into your function and let the process
block handle each element. You can also add a -PassThru
switch to it in case you also want the same object be returned as output for later manipulation. And lastly, it may be worth adding a new -Path
parameter to make it reusable.
function Write-Log {
param(
[Parameter(ValueFromPipeline, Mandatory)]
[object] $InputObject,
[parameter(Mandatory)]
[string] $Path,
[parameter()]
[switch] $PassThru
)
begin { $sb = [System.Text.StringBuilder]::new() }
process {
$sb = $sb.AppendLine("$(Get-Date) - $InputObject")
if($PassThru.IsPresent) { $InputObject }
}
end { Add-Content $Path -Value $sb.ToString() -NoNewline }
}
$FileList = Get-ChildItem -Path .\* -Include '*.csv', '*.xlsx' |
Write-Log -Path "G:\Folder\TestLog.log" -PassThru