Peter Core
Peter Core

Reputation: 303

Get-ChildItem & Export-Csv with Path from $_.basename

I need to add a patch to a filename when exporting which is generated from the Get-Childitem.

Get-ChildItem 'C:\temp\*.txt' | foreach-Object {
*some magic here*
} | export-csv -NoTypeInformation -Force -Encoding UTF8 ($_.basename + ".txt")

Works fine, but now I want to add a path to the resulting txt files.

I changed the code to

| export-csv -NoTypeInformation -Force -Encoding UTF8 -path "c:\temp\csv_temp\"($_.basename + ".csv")

which failed. I also tried:

| export-csv -NoTypeInformation -Force -Encoding UTF8 ("c:\temp\test\"+ $_.basename + ".txt")

also with the same result.

Upvotes: 1

Views: 2061

Answers (1)

mklement0
mklement0

Reputation: 439277

The ($_.basename + ".txt") in your Export-Csv call cannot work, because $_ is not defined when used directly as a parameter value, outside of a script block.

(Unless you had explicitly assigned an object with a .basename property to $_ beforehand - which you shouldn't do - $_ is undefined, so ($_.basename + ".txt") evaluates to ".txt", and you're effectively outputting to a file named .txt.)

You generally cannot use $_ - or even a variable passed from an earlier pipeline stage with the -PipelineVariable / -pv common parameter - as a direct parameter value, outside of a script block.[1]

Therefore, I suggest you restructure your command as follows (making use of the PSv4+ -pv / -PipelineVariable common parameter for convenience, but it's easy to adapt the solution to PSv3-):

Get-ChildItem 'C:\temp\*.txt' -pv fileObj | ForEach-Object {
  *some magic here* |
    Export-Csv -NoTypeInformation -Force -Encoding UTF8 ($fileObj.basename + ".txt")
}

By moving the Export-Csv call into the ForEach-Object script block, you can make use of the $fileObj variable created by -pv fileObj, representing the input file at hand.

While the input file is also reflected in $_ inside the script block, $_ is redefined in the context of the embedded pipeline, so -pv fileObj is a convenient way to create a variable that refers to the outer pipeline's input object as $fileObj; alternatively, you could execute $fileObj = $_ at the start of the script block, which makes the solution work in PSv3- too.

The alternative target-file-path arguments are then:

# Using an expandable string with an *embedded* expression:
# Note the $(...) surrounding the expression
"c:\temp\csv_temp\$($fileObj.basename + ".csv")"

# Using an expression (string concatenation):
("c:\temp\test\" + $fileObj.basename + ".txt")

[1] The reason is that directly passed values are bound to their parameter variables before any objects are sent through the pipeline.

Upvotes: 2

Related Questions