Sesame PowerShell : Scripting Text Files
Again I will mimic a Scripting Guy article here in PowerShell, only this time from the Sesame Script series :
Sesame Script: Scripting Text Files
Preamble
As this entry also was written as a training for the International Winter Scripting Games,
And just to make you feel even better about entering, this month’s Sesame Script will help you through at least one of the events, so you should be able to enter that one (or ones).
As there was no PowerShell content in the Article (probably because the Scripting Guys did think this was to easy in PowerShell, or that we have to much advantage over the VbScript competitors already (and they are right ;-) )
but still here is the PowerShell version ( as there is a lot of explanation in the origional article, it's best to follow this besides the original Article and compare the PowerShell solutions given here to the VbScript ones , I use the same headers in this Blogitem to make it easy to keep them in sync )
Creating a Text File
The first step is not really needed in PowerShell but you can do it like this :
New-Item -ItemType file freespace.txt
This is the same as the second example in the Script ( do not overwrite the File is it does exist ) , to force the file to be overwritten as it does allready exist as in the first VbScript sample use the -Force Parameter, See examples Below
PoSH> New-Item -ItemType file freespace.txt
Directory: Microsoft.PowerShell.Core\FileSystem::C:\PowerShell
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 2/8/2007 7:59 PM 0 freespace.txt
PoSH> New-Item -ItemType file freespace.txt
New-Item : The file 'C:\PowerShell\freespace.txt' already exists.
At line:1 char:9
+ New-Item <<<< -ItemType file freespace.txt
PoSH> New-Item -ItemType file freespace.txt -Force
Directory: Microsoft.PowerShell.Core\FileSystem::C:\PowerShell
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 2/8/2007 7:59 PM 0 freespace.txt
PoSH>
Bonus We mentioned that this might be something you want to do every day: keep a log for each day.
In that case, you’d probably want to give the file a new name each day. It makes sense, then, to base the file name off of the current date. So let’s take a look at a script that will do just that:
Note that I changed the date format a bit for sortability :
$date = ( get-date ).ToString('yyyyMMdd')
$file = New-Item -type file "$date-freespace.txt"
Note that this time I "catch" the result in a Variable $file (This is the same fileInfo object as $file = get-item 20070208-freespace.txt would give), that I keep for reference.
PoSH> $date = ( get-date ).ToString('yyyyMMdd')
PoSH> $file = New-Item -type file "$date-freespace.txt"
PoSH> $file
Directory: Microsoft.PowerShell.Core\FileSystem::C:\PowerShell
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 2/8/2007 8:10 PM 0 20070208-freespace.txt
PoSH>
Closing a Text File
n/a
Writing to Text Files
Okay, we’ve created a text file, now it’s time to actually put some text into this file. Let’s start by reading in some information from the computer that we want to add to our text file. Suppose we want to keep track of the amount of free space on the C: drive of the computer. We do that like this:
Here the fun realy starts, as a VbScript is used to get some information to write to the created file
In PowerShell we can use the Get-WMIObject (GWMI) Cmdlet for this, as all properties are retrieved now we coul use :
Get-WmiObject Win32_LogicalDisk -filter "DeviceID = 'C:'"
but as GWMI has also a -Query Parameter we can also use the Query Method as in the VbScript example :
Get-WmiObject -Query "Select * from Win32_LogicalDisk Where DeviceID = 'C:'"
PoSH> gwmi -q "Select * from Win32_LogicalDisk Where DeviceID = 'C:'"
DeviceID : C:
DriveType : 3
ProviderName :
FreeSpace : 4052410368
Size : 39966633984
VolumeName :
PoSH>
Next in the Original article we write the FreeSpace to the Textfile,
Now, back to our text file. Rather than echoing our output to the screen we want to save this value to the file.
To Show off a bit I will Show a PowerShell Oneliner here that will do the same as all code so far (creates the file if not exists otherwise will create it ):
(gwmi Win32_LogicalDisk -filter "DeviceID = 'C:'").freespace >> "$(( get-date ).ToString('yyyymmdd'))-freespace.txt"
But will go on in parts using variables as that is more Clear, lets look at your commands this far :
$date = ( get-date ).ToString('yyyyMMdd')
$file = New-Item -type file "$date-freespace.txt"
$wmi = gwmi -q "Select * from Win32_LogicalDisk Where DeviceID = 'C:'"
add-content $file $wmi.FreeSpace
PoSH> $date = ( get-date ).ToString('yyyyMMdd')
PoSH> $file = New-Item -type file "$date-freespace.txt"
New-Item : The file 'C:\PowerShell\20070208-freespace.txt' already exists.
At line:1 char:17
+ $file = New-Item <<<< -type file "$date-freespace.txt"
PoSH> $file = New-Item -type file "$date-freespace.txt" -Force
PoSH> $wmi = gwmi -q "Select * from Win32_LogicalDisk Where DeviceID = 'C:'"
PoSH> add-content $file $wmi.FreeSpace
PoSH> Get-Content $file
4052082688
PoSH> $file.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True FileInfo System.IO.FileSystemInfo
PoSH>
Note that I not give a filename to the Get-Content Cmdlet but the FileInfo Object I got back from New-Item, hence I do not have to worry about the filename.
This is because PowerShell is Object based, and the Get-Content Cmdlet does "Understand" a FileInfo Object.
And next some Formatting is Added :
* PoSH Bonus* As bytes are not that readable with current Harddisk sizes, we can do better by converting it to Megabytes and rounding at 2 digits :
PoSH> $file = New-Item -type file "$date-freespace.txt" -Force
PoSH> $wmi = gwmi -q "Select * from Win32_LogicalDisk Where DeviceID = 'C:'"
PoSH> $Free = "{0:n2}" -f ($wmi.FreeSpace / 1mb)
PoSH> $Size = "{0:n2}" -f ($wmi.Size / 1mb)
PoSH> add-content $file "Free space (in Megabytes): $free"
PoSH> add-content $file "Total space (in Megabytes): $Size"
PoSH> type $file
Free space (in Megabytes): 3,864.69
Total space (in Megabytes): 38,115.15
PoSH>
Opening a Text File
n/a
Reading from Text Files
One of the easiest ways to cycle through a list of computers is to put that list into a text file. An added bonus to this approach is that it’s simple to go in and add and remove computer names as necessary. Let’s say our list looks like this:
atl-fs-01
atl-fs-02
atl-fs-03
atl-fs-04
atl-fs-05
We save this list in a text file that we name Servers.txt. Let’s start with a simple script that will read this list of computers from the text file and display the results to the screen:
* PowerShell Bonus * Here I first create the list by using a "Here String" everything between @' '@ will be considered text, and you can just past in a list like this in an interactive prompt :
PoSH> Set-Content Servers.txt @'
>> atl-fs-01
>> atl-fs-02
>> atl-fs-03
>> atl-fs-04
>> atl-fs-05
>> '@
>>
PoSH> Get-Content Servers.txt
atl-fs-01
atl-fs-02
atl-fs-03
atl-fs-04
atl-fs-05
PoSH>
Now we can easy combine this with the former work we did (as the servers where not there all is 0, but for the idea ):
PoSH>
PoSH> Get-Content Servers.txt |% {
>> $wmi = gwmi -q "Select * from Win32_LogicalDisk Where DeviceID = 'C:'" -Computer $_
>> $Free = "{0:n2}" -f ($wmi.FreeSpace / 1mb)
>> $Size = "{0:n2}" -f ($wmi.Size / 1mb)
>> add-content $file "Computer : $_"
>> add-content $file "Free space (in Megabytes): $free"
>> add-content $file "Total space (in Megabytes): $Size"
>> Add-Content $file ""
>> }
>>
Get-WmiObject : The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)
At line:2 char:12
PoSH> Get-Content $file
Computer : atl-fs-01
Free space (in Megabytes): 0.00
Total space (in Megabytes): 0.00
Computer : atl-fs-02
Free space (in Megabytes): 0.00
Total space (in Megabytes): 0.00
Computer : atl-fs-03
Free space (in Megabytes): 0.00
Total space (in Megabytes): 0.00
Computer : atl-fs-04
Free space (in Megabytes): 0.00
Total space (in Megabytes): 0.00
Computer : atl-fs-05
Free space (in Megabytes): 0.00
Total space (in Megabytes): 0.00
Reading and Writing from the Same File
And to save the most fun to the last :
(get-content companies.txt) -replace 'Fabrikam','Contoso' | out-file companies.txt
PoSH> gc Companies.txt
Ken Myer
Fabrikam
Pilar Ackerman
Wingtip Toys
Jeff Hay
Fabrikam
Ellen Adams
Northwind Traders
PoSH> (get-content companies.txt) -replace 'Fabrikam','Contoso' | out-file companies.txt
PoSH> type Companies.txt
Ken Myer
Contoso
Pilar Ackerman
Wingtip Toys
Jeff Hay
Contoso
Ellen Adams
Northwind Traders
PoSH>
Read and Write Your Way to a Perfect Score
If you understood anything at all in this article, you’ll do great in the Scripting Games (PowerShell Competition). We can’t guarantee a perfect score for everyone (some of the events are still going to be pretty tough), but you’ll most likely make a pretty good showing.
You can see that PowerShell the PowerShell Comptition may be not that hard ;-)
Enjoy,
Greetings /\/\o\/\/