PS Скрипт экспортирует пустые CSV
Я чертовски стараюсь понять, почему этот скрипт не работает так, как задумано. Это простой скрипт, в котором я пытаюсь импортировать CSV, выбрать несколько нужных столбцов, затем экспортировать CSV и скопировать сам. (По сути, мы заархивировали данные, из-за которых мне не хватало объема памяти, мне нужно всего несколько столбцов для другого проекта). Этот сценарий очень прост, и, очевидно, имеет обратную зависимость от того, какое разочарование он вызывает, когда он не работает... Прямо сейчас конечный результат - я получаю пустой CSV вместо CSV, содержащего только выбранные мной столбцы. с помощью Select-Object.
$RootPath = "D:\SomeFolder"
$csvFilePaths = Get-ChildItem $RootPath -Recurse -Include *.csv |
ForEach-Object{
Import-CSV $_ |
Select-Object Test_Name, Test_DataName, Device_Model, Device_FW, Data_Avg_ms, Data_StdDev |
Export-Csv $_.FullName -NoType -Force
}
3 ответа
Если вы не прочитаете входной файл в память полностью, заранее, вы не сможете безопасно читать и записывать обратно в один и тот же файл в данном конвейере.
В частности, такая команда, как Import-Csv file.csv | ... | Export-Csv file.csv
сотрет содержимое file.csv
,
Самое простое решение - заключить команду, которая читает входной файл в (...)
, но обратите внимание, что:
Содержимое файла (преобразованное в объекты) должно помещаться в памяти в целом.
Существует риск потери данных, если конвейер прерывается до того, как все (преобразованные) объекты будут записаны обратно в файл.
Применительно к вашей команде:
$RootPath = "D:\SomeFolder"
Get-ChildItem $RootPath -Recurse -Include *.csv -OutVariable csvFiles |
ForEach-Object{
(Import-CSV $_.FullName) | # NOTE THE (...)
Select-Object Test_Name, Test_DataName, Device_Model, Device_FW,
Data_Avg_ms, Data_StdDev |
Export-Csv $_.FullName -NoType -Force
}
Обратите внимание, что я использовал -OutVariable csvFiles
для того, чтобы собрать объекты CSV file-info в выходной переменной $csvFiles
, Ваша попытка собрать пути к файлам через $csvFilePaths = ...
не работает, потому что пытается собрать Export-Csv
выходной, но Export-Csv
не производит никакого вывода.
Кроме того, чтобы быть в безопасности, я изменил Import-Csv
аргумент от $_
в $_.FullName
чтобы убедиться, что Import-Csv
находит входной файл (потому что, к сожалению, объект file-info $_
связан как строка, которая иногда расширяется до простого имени файла).
Более безопасным решением было бы сначала вывести во временный файл и (только) при успешном завершении заменить исходный файл.
При любом подходе файл замены будет иметь атрибуты файла по умолчанию и разрешения; если исходный файл имел специальные атрибуты и / или разрешения, которые вы хотите сохранить, вы должны воссоздать их явно.
Как прокомментировал Мэтт, ваш последний $PSItem ($_)
не связано с Get-ChildItem
больше, но для Select-Object
Командлет, который не имеет FullName
Имущество
Вы можете использовать другой подход foreach:
$RootPath = "D:\SomeFolder"
$csvFilePaths = Get-ChildItem $RootPath -Recurse -Include *.csv
foreach ($csv in $csvFilePaths)
{
Import-CSV $csv.FullName |
Select-Object Test_Name,Test_DataName,Device_Model,Device_FW,Data_Avg_ms,Data_StdDev |
Export-Csv $csv.FullName -NoType -Force
}
Или сохраняя свой код, добавьте $CsvPath
Переменная, содержащая путь CSV и использовать его позже:
$RootPath = "D:\SomeFolder"
Get-ChildItem $RootPath -Recurse -Include *.csv | ForEach-Object{
$CsvPath = $_.FullName
Import-CSV $CsvPath |
Select-Object Test_Name,Test_DataName,Device_Model,Device_FW,Data_Avg_ms,Data_StdDev |
Export-Csv $CsvPath -NoType -Force
}
Итак, я понял это. Я пытался напрямую передать командлет Import-Csv вместо объявления его в качестве переменной в коде og. Вот фрагмент кода, который получает то, что я хотел сделать. Я пытался передать конвейер непосредственно в командлет Import-Csv, мне просто нужно было объявить переменную, использующую командлет Import-Csv в качестве определения, и направить эту переменную в Select-Object, а затем в командлеты Export-Csv. Спасибо всем за помощь, я ценю это!
$RootPath = "\someDirectory\"
$CsvFilePaths = @(Get-ChildItem $RootPath -Recurse -Include *.csv)
$ColumnsWanted = @('Test_Name','Test_DataName','Device_Model','Device_FW','Data_Avg_ms','Data_StdDev')
for($i=0;$i -lt $CsvFilePaths.Length; $i++){
$csvPath = $CsvFilePaths[$i]
Write-Host $csvPath
$importedCsv = Import-CSV $csvPath
$importedCsv | Select-Object $ColumnsWanted | Export-CSV $csvPath -NoTypeInformation
}