Friday, April 13, 2007 11:29 PM
Powershell, is a great tool for handy scripting. It is often needed that you need to write sql scripts in isolated files. The is good in terms of finding errors in script, and focusing on one part while developing part of the sytem.But , as the number of script files grows big , the deployment issue becomes a headache for the release manager to handle your scripts.
I used to think that the best solution, for merging files, is to use dos copy /xcopy commend, but this often gets screwed up for really big scripts having evernt large srings within.
Though .Net has rich libray for that,it not aways easy to make a console app which i can share with my collegues, therefore i started tiny a powershell that made my life more easier.
The goal of my power shell, i will give source dirercoty , exetenstion(filetype to be included in merge) and optionally a diliminator(for ex. i want to have "GO" keyword at end of each sql file).
Logic:
Get all files for provided extenstion
Read the whole content, and append it in a string builder
Add the diliminator
Finally Combine them to one file.
Code
Param ($source="c:\Test", $extenstion ="*.sql", $outputFile = "outputFile.sql" , $blockTerminator = "GO" )
[System.IO.DirectoryInfo]$directoryInfo = New-Object System.IO.DirectoryInfo($source);
$rgFiles = $directoryInfo.GetFiles($extenstion);
$builder = New-Object System.Text.StringBuilder;
foreach ($fileInfo in $rgFiles)
{
[System.IO.FileStream]$fReader = $fileInfo.OpenRead();
if (-not ($fileInfo -eq $null))
{
write $fileInfo.Name;
$reader = New-Object System.IO.StreamReader($fReader);
$builder.AppendLine($reader.ReadToEnd());
$builder.AppendLine($blockTerminator);
}
}
if (-NOT $source.EndsWith('\'))
{
$source = $source + '\';
}
$outputFile = $source + $outputFile;
[System.IO.FileStream]$fWriter = New-Object System.IO.FileStream($outputFile, [System.IO.FileMode]::OpenOrCreate);
$writer = New-Object System.IO.StreamWriter($fWriter);
$writer.Write($builder.ToString());
$writer.Flush();
$writer.Close();
Terminology
Param - This excepts user input from shell, optionally you set default value
All the status methods in .net are called with double "::".
Classes are declared with fully quilifed name
New-Object : use for class declartion , optionally you can use -comObject to declare com objects.
How to use
Copy the code , paste it in a text file , rename it to .ps1 extenstion.
Get the exeution poiicy of your shell enviroment , by default it is Restricted , you can know that from calling Get-ExecutionPolicy command. In this mode you cant run scriptlets. Use Set-ExecutionPolicy RemoteSinged.
Run the script , do add the ".\" sign before your file name.
Example
PS C:\Users\mehfuz> .\FileMerge.ps1 basedirectory extension mergedFile.sql blockdeliminator
Ex ./Filemerger.ps1 c:\test *.sql mehfuz.sql GO
Enjoy!