Each month we receive 30 text files containing various medical claim responses. We sort these into three subfolders and then consolidate and load them into a database table for analysis.
This may not be the wisest way to do this, so feel to include better methods in addition to code review, but I'm learning Powershell and trying to use it to accomplish two things:
- Add a column (either in memory or in the actual file) to text files containing several undelimited columns of known (fixed) lengths
- The new column's data would simply be the name of the current file
- The new column would be of unknown (variable) length
- When the text files are combined into a single CSV and loaded into a database table, the new column tells user the source file of a record so they can refer back to it if needed
- The source files are located in separate subfolders - each subfolder gets its own consolidated csv/table.
- Combine all of the modified text files into a single csv for load into Teradata via Teradata FastLoad
- The text files can be up to 5GB in combined size
The script works, but pretty slowly. We were previously doing this via a batch file containing Perl, but the Perl broke and I thought Powershell had numerous possible advantages for this task:
- Already installed on every user's computer - new task managers do not need to request Perl via the IT software pipeline
- Future maintainers can learn one language instead of 2 (Batch and Perl)
I've included the previous batch file for comparison:
The Powershell file I wrote:
#Powershell -executionpolicy bypass -file "\\(directory 1)\Create Consolidated CSV.ps1"
function ConsolidateResponseFile($plan, $fileindex) {
$pathPlanResponseFileCSV = ($_.FullName + ([System.IO.Path]::DirectorySeparatorChar) + "Consolidated_Response_File.csv")
if (Test-Path $pathPlanResponseFileCSV) {
Remove-Item $pathPlanResponseFileCSV
}
$originalFiles = Get-ChildItem -Path ($_.FullName + ([System.IO.Path]::DirectorySeparatorChar) + "*.txt") -Attributes !Directory
$originalFiles | ForEach-Object {
$fileindex = $fileindex + 1
$fileName = $_.Name
$csv = import-csv $_ -Header Stage_Data , File_Name
$csv | ForEach-Object {
$_.File_Name = $fileName
}
$percent = $fileindex/$totalfiles*100
Write-Progress -Activity "Consolidating text file data..." `
-PercentComplete $percent `
-CurrentOperation $fileName `
-Status "$percent% Complete"
$finalcsv = $finalcsv + $csv
}
$percent = $fileindex/$totalfiles*100
Write-Progress -Activity "Writing final csv..." `
-PercentComplete $percent `
-CurrentOperation $fileName `
-Status "$percent% Complete"
$finalcsv | export-csv -LiteralPath $pathPlanResponseFileCSV -NoTypeInformation
$fileindex
}
$allResponseFilesForMonth = "\\(directory 2)\"
$files = Get-ChildItem -path "$allResponseFilesForMonth*.txt" -Attributes !Directory -Recurse
$totalfiles = $files.Count
$planFolders = Get-ChildItem -path $allResponseFilesForMonth -Attributes Directory
$fileindex = 0
$planFolders | ForEach-Object {
$plan = $_
ConsolidateResponseFile $plan, $fileindex
$fileindex = ConsolidateResponseFile
}
For comparison, the previous Batch script (which makes individual CSVs first and does only one subfolder):
pushd \\(directory)\
REM copy original files
copy *.TXT *.csv
REM Add filename to end of each record.
net use b: /delete /y
net use b: "\\(directory)\"
for /f %%a IN ('dir /b "\\(directory)\*.csv"') do (perl -i.bak -p -e "s/\n/|$ARGV\n/" %%a )
REM Copy all csvs to one master csv
copy *.csv Consolidated_Response_File.csv
Here's some test data to use. There will be 30 .txt files, and for the subfolder with 20 of them, they can be up to a combined 5GB in size.
Before data for FileName1.txt
250CharactersOfUndelimitedFixedLengthData1
250CharactersOfUndelimitedFixedLengthData2
250CharactersOfUndelimitedFixedLengthData3
250CharactersOfUndelimitedFixedLengthData4
250CharactersOfUndelimitedFixedLengthData5
After data for FileName1.txt
250CharactersOfUndelimitedFixedLengthData1,FileName1.txt
250CharactersOfUndelimitedFixedLengthData2,FileName1.txt
250CharactersOfUndelimitedFixedLengthData3,FileName1.txt
250CharactersOfUndelimitedFixedLengthData4,FileName1.txt
250CharactersOfUndelimitedFixedLengthData5,FileName1.txt