Jose3d
Jose3d

Reputation: 9277

Powershell access to a variable in previous pipe

I created the following command for merge all csv files that matches with a filter inside a folder and outputs it into an outfile.

$mainPath="C:\\users\\myuser\\temp";
$mergeFilter="myfile.csv";
$outFile = "C:\\users\\myuser\temp\test.csv";
Get-ChildItem $mainPath -Recurse -Include $mergeFilter |
    Select-Object -ExpandProperty FullName |
    Import-Csv -Delimiter ';' |
    Select-Object *,@{Name='Date'; Expression={"$dummyvariable"}}; |
    Export-Csv $outFile -NoTypeInformation -Delimiter ';'

My issue is that, I want to add an extra column when some CSV's are merged using a variable called $dummyvariable but I dont know where I have to initialize it in order to get the value in the Expression={"..."}. If I declare before in the pipeline it doesn't work (I need to do it higher on the pipe to get a directory name)

Do you know how I can declare this variable and recover on the pipe that starts with "Select-Object"?

Thanks in advance

Best Regards.

Jose

Upvotes: 6

Views: 7250

Answers (2)

mklement0
mklement0

Reputation: 438093

I think you're looking for the commmon -PipelineVariable (-pv) parameter (PSv4+), which stores a given cmdlet's current output object in a variable that can be referenced in script blocks in later pipeline segments.

Here's a simplified example:

# Create sample input file.
@'
foo;bar
1;2
'@ > file.csv

# NOTE: -pv fileObj (same as: -PipelineVariable fileObj)         
#       stores (potentially each) `Get-Item` output object in var. $fileObj, 
#       accessible in script blocks later in the the pipeline.
Get-Item file.csv -pv fileObj |
  Select-Object -ExpandProperty FullName | 
  Import-Csv -Delimiter ';' |
  Select-Object *, @{ n='Date'; e={ $fileObj.LastWriteTime } }

The above yields something like:

foo bar Date              
--- --- ----              
1   2   2/17/18 4:17:25 PM

That is, -pv fileObj made Get-Item store its current output object in variable $fileObj, which the last pipeline segment was able to reference in the property-definition script block.

Note:

  • Do not prefix the variable name with $ in the -pv / -PipelineVariable argument: the mere variable name must be passed (e.g. fileObj); only on accessing the resulting variable is $ required (e.g. $fileObj).

Upvotes: 9

G42
G42

Reputation: 10019

You should be able to use a ForEach-Object to specify $dummyvariable without affecting other elements of the pipeline.

$mainPath="C:\\users\\myuser\\temp";
$mergeFilter="myfile.csv";
$outFile = "C:\\users\\myuser\temp\test.csv";
Get-ChildItem $mainPath -Recurse -Include $mergeFilter |
    Select-Object -ExpandProperty FullName |
    Import-Csv -Delimiter ';' |
    ForEachObject {$dummyvariable = "..."} |
    Select-Object *,@{Name='Date'; Expression={"$dummyvariable"}}; |
    Export-Csv $outFile -NoTypeInformation -Delimiter ';'

This is untested. You may need to specify that the properties need to be passed along to the next pipeline by doing this:

ForEachObject {$dummyvariable = "...";$_} |

My approach would be to break things down though as advised by vonPryz. Makes it easier to debug and to maintain.

Upvotes: 0

Related Questions