Reputation: 181
I have been reading through some of the previous posts about the concept, but all the solutions i find very different from eachother.
I have multiple csv's devided over seperate folders (all with kind of the same path but the subfolders are different).
I now need to import these csv's, change the headers and export it into one single csv.
I have been trying with this but im getting a very weird error: Import-Csv : Cannot open file "C:\Windows\system32\Book1.csv" Although my path is refering to C:\csv ?
$CSVFolder = 'C:\csv\'; #'
$OutputFile = 'C:\export\test3.csv';
$CSV= @();
Get-ChildItem -Path $CSVFolder -Filter *.csv | ForEach-Object {
$CSV += @(Import-Csv -Path $_)
}
$CSV | Export-Csv -Path $OutputFile -NoTypeInformation -Force;
I was thinking of using a datatable for the headers, but its not so clear to me at this point. Also the issue with the error is not clear for me...
Upvotes: 1
Views: 2832
Reputation: 440142
As has been noted:
Import-Csv -Path $_
should be Import-Csv -Path $_.FullName
in your code,
Import-Csv -LiteralPath $_.FullName
, because strings passed to the -Path
parameter are subject to wildcard resolution).because the [System.IO.FileInfo]
instances representing files returned by Get-ChildItem
are converted to strings when they are passed to the -Path
(or -LiteralPath
) parameter as a command-line argument (as opposed to via the pipeline), in which case the the mere file name rather than the full path is used, if your Get-ChildItem
command targets a directory in Windows PowerShell (see background information below).
A mere filename such as Book1.csv
is interpreted as relative to the current directory (which happened to be C:\Windows\system32
in your case), so Import-Csv
looks for file C:\Windows\system32\Book1.csv
rather than the intended C:\csv\Book1.csv
.
Note that piping Get-ChildItem
output to cmdlets is generally not affected by this, because the .PSPath
property (which PowerShell adds behind the scenes) containing the full path (including PS provider prefix) binds to the -LiteralPath
parameter.
Note that as of PSv5.1.14393.693, however, this mechanism is broken for Import-Csv
, due to a bug.
This is a common pitfall that occurs whenever [System.IO.FileInfo]
instances are passed to cmdlets that accept file paths via [string]
(-array)-typed parameters as arguments.
To be safe: Always use .FullName
when you pass objects received from Get-ChildItem
to another command as a parameter value (as opposed to via the pipeline) to ensure that the full path is passed.
This behavior is a pitfall, because it is perfectly reasonable to assume that passing a [System.IO.FileInfo]
instance as-is to a command that accepts file paths works, given the object-oriented nature of PowerShell - especially, since it does work reliably when using the pipeline rather than a parameter value.
Unfortunately, the built-in cmdlets that accept file paths (-Path
, -LiteralPath
parameters) do so as [string]
s only (there is no parameter set that accepts [System.IO.FileInfo]
instances directly), and it is in the course of [System.IO.FileInfo]
-to-string conversion that the problem arises.
There also wouldn't be a problem if the [System.IO.FileInfo]
instances consistently evaluated to the files' full paths, which is unfortunately not the case in Windows PowerShell (this has since been fixed in PowerShell Core):
Get-ChildItem <directory>
outputs [System.IO.FileInfo]
instances that evaluate to file names only in a string context.
Get-ChildItem <literalFilePathOrWildCardExpr>
outputs [System.IO.FileInfo]
instances that evaluate to full paths.
In other words: It is only if Get-ChildItem
targets a directory (folder) that the objects it returns evaluate to their file names only in a string context.
Targeting a specific file or using a wildcard expression results in full paths, by contrast; with Get-Item
, that's always the case.
Upvotes: 1
Reputation: 17492
try this code. This code take all csv file, import them and take only column 1, 2, 3 and change column name to header1, header2, header3, then export all into new csv file
Get-ChildItem "C:\temp2" -Filter "*.csv" |
%{Import-Csv $_.FullName -Header header1, header3,header4} |
Export-Csv "c:\temp\result.csv" -NoTypeInformation
#a short version (for no purist)
gci "C:\temp2" -Filter "*.csv" | %{ipcsv $_.FullName -Header header1, header3,header4} | epcsv "c:\temp\result.csv" -NoType
Upvotes: 0
Reputation: 6615
You simply need to 'fullname' property, instead of 'name'.
Ex:
PS /Users/adil/Downloads> gi *csv |select name
Name
----
tradesdownload.csv
PS /Users/adil/Downloads> gi *csv |select name, fullname
Name FullName
---- --------
tradesdownload.csv /Users/adil/Downloads/tradesdownload.csv
Upvotes: 0