Como devolver o item atual de volta ao pipeline?
Atualmente estou importando arquivos csv e carregando em massa para a tabela sql.
usando este código
$CSVDataTable = Import-Csv $csvFile | % -begin {$i=0} -process { Write-Progress -activity "Importing file" -currentOperation "Reading line $i" -PercentComplete -1; $i++; return $_ } | Out-DataTable
Consigo mostrar o progresso, mas gostaria de otimizá-lo e uma recomendação que encontrei é a utilização de StreamReader.
então eu tentei o seguinte:
[int]$LinesInFile = 0 $reader = New-Object IO.StreamReader $csvFile $line = $reader.ReadLine() while($reader.ReadLine() -ne $null) { $LinesInFile++ }
$CSVDataTable = 0..($LinesInFile-1) | foreach {
$percent = ($_/$LinesInFile)*100 Write-Progress -Activity 'Importing from CSV' -Status "$percent % Complete" -CurrentOperation "Importing row # $($_+1)" -PercentComplete $percent; return $reader[$_] } | Import-Csv $csvFile | Out-DataTable
Erro (devido a ):return $reader[$_]
Import-Csv : The input object cannot be bound to any parameters for the command either because the command does not take pipeline input or the input and its
properties do not match any of the parameters that take pipeline input.
Respostas
A única coisa que faz sentido Import-Csvsão as System.IO.FileInfoinstâncias que representam arquivos CSV , como a saída por Get-ChildItem(que, à parte, é interrompida devido a um bug no Windows PowerShell, desde que corrigido no PowerShell [Core] v6 +).
Se você quiser relatar o andamento de uma Import-Csvchamada, coloque um ForEach-Objectcomando depois dela, no qual você pode emitir a mensagem de andamento e, em seguida, passar Import-Csvo objeto de saída ( $_) por meio de:
# Count the data rows in the input CSV file.
$rowCount = 0
switch -File $csvFile { default { ++$rowCount } }
--$rowCount # subtract 1 from the line count to account for the header row. Import-Csv $csvFile | ForEach-Object -Begin { $i = 0 } { $percent = '{0:N1}' -f (++$i / $rowCount * 100)
Write-Progress -Activity 'Importing from CSV' -Status "$percent % Complete" -CurrentOperation "Importing row # $i" -PercentComplete $percent $_ # pass the object from Import-Csv through.
} | Out-DataTable
# Hide the progress bar now.
# (Otherwise it would linger until the script as a whole completes.)
Write-Progress '(unused))' -Completed
É importante notar que as chamadas por objeto Write-Progressdiminuem significativamente a execução (e contar o número de linhas na frente também tem seu custo, assim como apenas a passagem de objetos por meio de uma ForEach-Objectchamada).
Uma maneira simples de reduzir a lentidão é usar apenas Write-Progresspara todos os N objetos , como todos os 100objetos no exemplo a seguir:
# Count the data rows in the input CSV file.
$rowCount = 0 switch -File $csvFile { default { ++$rowCount } } --$rowCount # subtract 1 from the line count to account for the header row.
Import-Csv $csvFile | ForEach-Object -Begin { $i = 0 } {
if (++$i % 100 -eq 1 -or $i -eq $rowCount) { $percent = '{0:N1}' -f ($i / $rowCount * 100)
Write-Progress -Activity 'Importing from CSV' -Status "$percent % Complete" -CurrentOperation "Importing row # $i" -PercentComplete $percent } $_ # pass the object from Import-Csv through.
} | Out-DataTable
# Hide the progress bar now.
# (Otherwise it would linger until the script as a whole completes.)
Write-Progress '(unused))' -Completed
Nota: Se Out-DataTablerequer uma quantidade não trivial de tempo de processamento após o último objeto ter sido passado para ele, você pode preencher o número de linhas para fins de exibição de porcentagem com base em uma estimativa desse tempo adicional, como uma porcentagem da linha verdadeira contagem.