CEG 233: Linux and Windows

Notes on Scripting with PowerShell

This article is a brief introduction to PowerShell at a level suitable for our course CEG233. For more details, see the listed references. It assumes that the CEG 233 Bash Introduction has happened, and that you are familiar with control structures.  It also expects you to read the PowerShell book chapter(s) given in the References.  PowerShell is a sophisticated scripting language.  In particular, PowerShell error messages are too cryptic.  So do not get discouraged if some issues are too hard to understand, and do not get disappointed because CEG233 omits many items.  PowerShell is a "large" language.  In CEG 233, we cover a small subset of the language.    In particular, we do not dwell on its object-oriented features.  Our coverage is implied by the sections this article has.

Table of Contents

  1. Educational Objectives
  2. Windows  PowerShell
  3. PowerShell Overview
  4. Variables
  5. Script Files
    1. For loops
    2. If code-blocks
    3. Functions
  6. Acknowledgements
  7. References

Educational Objectives

The objectives of this article are to make you :

  1. Familiar with command line utilities of Windows
  2. Learn fundamentals of Windows PowerShell scripting

Windows PowerShell

In Windows XP and later, two shells (CLI, command line interpreter) are installed by default in the Windows partition.  The program known simply as cmd is now considered obsolete.  The newer shell is known as powershell; it is typically found in the Windows drive as

C:\Windows\system32\WindowsPowerShell\v1.0\powershell.exe
C:\Windows\system32\WindowsPowerShell\v1.0\powershell_ise.exe

(The version number may be different on the machine you are using. The above is actually PowerShell v2 despite the fact that the parent folder is named v1.0.) It can be invoked for interactive use through the Run... facility as an ordinary unprivileged user.  If you wish to execute privileged operations, "search" for powershell and then Run-as-administrator.  The powershell.exe is a plain looking console text application.  The powershell_ise.exe is a GUI application that includes script development and debugging support.

PowerShell is an interpreter for a language that has no explicit name; so, we often refer to it as the PowerShell language. In Windows, it is typical to see not only PowerShell but also Visual Basic, Perl and Python used for scripting purposes.

As you read this article, open a PowerShell window, and try the commands shown. Frequently, we omit explaining what can be readily seen and understood by trying it out.  PowerShell code is shown in a rectangle with Antique White background color.  For now, the prompt string. is omitted.

Remember that in Windows, file names and command names can be written in either upper or lower case. This is not just a PowerShell property.

1. PowerShell Quick Overview

  1. PowerShell contains variables, assignments, code-blocks, if-statements, loops, functions, etc. making it a programming language, but at a higher level than say Java, and one that deals with filenames, files, their permissions etc.. Such higher level languages are called scripting languages.
  2. PowerShell is a "large" language.  In CEG 233, we cover a small subset of the language.    In particular, we do not dwell on its object-oriented features.  Our coverage is implied by the sections this article has.
  3. PowerShell has a man command that is similar to Linux man.  Invoke
    1. man  (with no arguments), and
    2. man * (second word is just the asterisk).  This will give an overview what PowerShell has. 
    3. help
  4. Regular expressions (file-name regex) are supported.   Assuming that you have some files that begin with a dot, or have as their second character the letters A through G (lower or upper), try
    ls .* ?[A-G]*
  5. PowerShell has aliases, functions, and what are known as cmdlets. A "commandlet" is a short little script already understood by PowerShell. 
    1. Invoke gcm to see a list (gcm is an alias for  Get-Command). 
  6. PowerShell has pipes, and output redirection -- similar to those in Bash. Input redirection is expected to be implemented in a future version.
  7. PowerShell has many "commands" that have the same name as in Unix/Linux and perform (almost) the same operation.  Here is an incomplete list of these:

    alias, cat, cd, cp, diff, h, history, kill, ls, man, more, mkdir, mv,
    popd, pushd, ps, pwd, rmdir, rm, tee
    , ...

    However, the flags/options that you are used to in Linux may not be the same.  E.g., ls works, but ls -l will generate a complaint.  Several of the listed items are "aliases" in PS.

2. Lexical Structure

A sequence of characters ending with a carriage-return (the Enter key) that you type is divided into tokens (words), just like in English. Let us call them w0, w1, ... It is a distraction at this point to describe (all) the rules that govern the splitting of a line into words. In the examples, you will see one or two delimiters other than space. Let us just assume that the tokens we have do not contain spaces. 

(i) A trailing backtick character allows long commands to be split into multiple lines. (ii) Comments begin with the number-sign/hash (#) character and end at the end of that line.

3. Variables

Variable names are case insensitive, but for CEG233, think as if they are.  They must have a dollar sign in front. Some variables are predefined. 

echo $HOME $PROFILE $PSHOME $env:UserName

$HOME gives the path name of your home directory.  $PROFILE is where you store your PowerShell customizations, analogous to .bashrc

Variables can be introduced and assigned values as follows.

$a="hi "
$b=0123456789+1
$c="0123456789+1"
$d="$a there"
echo $a $b $c $d
write-host $a $b $c $d

The echo shown in the above can be dropped, but in CEG233 we keep it;  a list of just variable names on a line will print their values.

3.1 Environment

PowerShell has several variables whose values are saved and restored via the Windows registry. These are known as environment variables. Environment variables have $ENV: prefixed; we say that environment variables are stored in a separate namespace ENV:

$env:path

The $env:path is an environment variable of special importance to us. Its value is a list of path names of directories separated with semicolons. Unless the first word w0 of a command line is a full path name, PowerShell searches for a program named w0 in each of these directories in left-to-right order.

Just like ordinary variables, an environment variable can be changed by assignment. E.g., if we had installed cygwin in a partition named H:, we can update PATH as follows.

$ENV:PATH="H:\cygwin\bin;$ENV:PATH"

To make this change permanent, you must change it via Computer->Properties->Advanced Environment Variables -> System Variables -> Path.

Exercises

3.2 Arrays

$a=0, 1, 2, 3
$b=$a, 4, 5, 6, 7, 8  # elements of array a and then 4 to 8
$b[4], $a[3]

$exclusions = '*.com', '*.exe', '*.o', '*.obj', '*.class', '*.sys', `
   '*.dll', '*.dat', '*.log', '*.ini'
$exclusions[3]
$i=3
$exclusions[$a[$i]]

4. Interactive Use

Try the following (one line at a time).

echo $profile
gcm
gcm *
help
ls

4.1 The REPL

The acronym REPL stands for Read, Execute, Print, Loop of an interpreter.  The line that you type is read, divided into tokens, and based on w0 and the path-search results, a program (or cmdlet, or an alias, ...) is invoked.

echo hello > hello.txt
hello.txt
What did the above do? Now, try this:
./hello.txt

4.2 Keyboard Conveniences

4.3 Prompt String

Exercise: Our book uses a prompt string that includes the number of the command you are about to type.  How did he do that?  [Hint: echo $profile]

5. Script Files

A frequent use of PowerShell consists of just one line of text given interactively. Sophisticated use involves multiple lines collected into a file of text; such files are called script or batch files (and have a .ps1 extension).

A typical script file starts out with command lines (such as assignment, if, for, etc.) and calls to functions defined within this file as well as calls of other script files. Good programs and scripts all have comments. They will remind you what your program is actually doing months or years down the road.

You can certainly try control structures and loops interactively.  But they are better learnt with script files (see below).

5.1 Enable .ps1 Files

Windows, by default, disables running .ps1 scripts for security reasons.  You can enable executing of scripts as follows.  Execute PowerShell in administrator mode (right-click the PowerShell shortcut to find the option). Run this cmdlet:

set-executionpolicy remotesigned 
Now locally stored script files are enabled, but scripts arriving from remote sites must be signed. For more details, invoke get-help about_signing

5.2 Invoke a .ps1 File

# a beginner example named myScript.ps1

echo 'echo a few numbers'
for ($i=0; ($i -lt 10); $i=$i+3) {
  echo $i
}

function fewNumbers($start, $end, $step) {
  echo fewNumbers
  for ($i=$start; ($i -lt $end+10); $i=$i+$step) {
    echo $i
  }
}

fewNumbers 200 280 4

Type a line beginning with dot alone as w0, and the name of the script file as w1.

.  myScript.ps1

5.3 If Statement

There are many different uses of if code-blocks. We can compare strings, check if a file exists, check the exit code of the last program, etc. The overall structure is as follows.

if  (condition) {
    code-block1
} else {
    code-block2
}

The condition is evaluated as a Boolean expression.  If true, code-block1 is executed, code-block2 is skipped. If false, code-block1 is skipped, code-block2 is executed. In simple situations, the braces can be omitted.

5.4 While Loop

The following generates the Fibonacci numbers less than 100.  It also shows a use of multiple assignments where LHS is a list of variable, and RHS is a same length list of values.  In ($c -lt 100), minus-lt stands for less-than.

$c = $p = 1;
while ($c -lt 100) {
  $c;
  $c,$p = ($c+$p),$c
}

There are two other variations,  do .. while (B) and do .. until (B), that are skipped in CEG 233.

Exercises

5.5 For Loops

Here  are a couple of little examples.  The for loop is similar to what C++ and Java have.  To save vertical space, the first loop is written in one line.  In general, trying to save vertical space is not a good idea.

for ($i=0; $i -lt 5; $i++) { $i }
foreach ($f in dir *.*) {
  $sz = $f.length
  $ex = $f.extension
  $fn = $f.name                    # unused var
  echo "File $f has $sz bytes. Its extension is $ex."
}

In the above the command dir *.* supplies the list for the "in" operator.  This command can be replaced by any other that produces a list of items.

Exercises

5.6 Functions

Function definitions look like this:

function name ( $param1, $param2, ... ) {
   statement-list
}

Recall the fewNumbers 200 280 4 example. A function is invoked in a way similar to Bash. Name of the function as w0, and its arguments as w1, w2, ...

6. Examples

Examples with prompt string 'PS> ' are from http://en.wikipedia.org/wiki/Windows_PowerShell .  (Examples marked with an asterisk will not appear in CEG233 exams.)
  1. The backtick (on the key below the ESC) provides an escape when you want to include meta characters as ordinary.
    echo $HOME `$HOME  hi,` there!  hi`,` there!
  2. List files dropping the (last) extension:
    ls | select basename 
  3. Below we create two files wth crazy names. Check their file sizes.  Can you trust the extensions any more?
    echo junk > 'fileName-with-difficultToDealWithChars.pdf_(dated_2009-10-32).pdf'
    write-host > 'fileName-with-difficult To Deal With;    Chars.pdf.adobe.pdf.exe'
    
  4. We can get the effect of input redirection as follows:
    cat inputFnm.txt | psScript.ps1
    
    This feeds the content of file named inputFnm.txt to psScript.ps1. By now, you know that cat is an alias for get-content
  5. End all processes that begin with the letter p:
     PS> ps p* | kill
  6. Find the processes that use more than 1000 MB of memory and kill them.  The token $_ refers to the "current object".  This example uses the WS member of the object referenced by $_.
    PS> ps | ? { $_.WS -gt 1000MB } | kill
  7. Calculate the number of bytes in the files in a directory:
    PS> ls  | measure length -s
  8. Determine whether a specific process is no longer running.  Start notepad and then try:
    PS> (ps notepad).WaitForExit()
  9. Insert the string 'ABC' after the first character in the word 'string' to have the result 'sABCtring':
    PS> 'string'.Insert(1, 'ABC')
  10. * Download a specific RSS feed and show the titles of the 8 most recent entries:
    PS> $rssUrl = 'http://blogs.msdn.com/powershell/rss.aspx'
    PS> $blog = [xml](new-object System.Net.WebClient).DownloadString($rssUrl)
    PS> $blog.rss.channel.item | select title -first 8
    $x=new-object xml;$x.load('http://blogs.msdn.com/powershell/rss.aspx');$x.rss.channel.item|select title -f 8
  11. Run a command line executable, e.g., C:\Windows\System32\tracert.exe, with arguments. 
    PS>  $arguments = '-h', '15', 'www.google.com'
    PS>  tracert  $arguments
  12. Exercise: Ampersand as w0. Try the next line with and without the ampersand. Try with and without the quotes.
    & "ls"
    
  13. Measure-Command is like the time prefix of bash.
    measure-command { ls }
    
  14. Prompting for input:
    $nm = Read-Host "Enter your name"
    Write-Host "Hello" $nm
    
  15. Change prompt (watch the window title!) (from http://mshforfun.blogspot.com/ )
    function prompt {
     $host.ui.rawui.WindowTitle = "Files: " + `
      (get-childitem).count + " Process: " + (get-process).count
     Write-Host ("PS " + $(get-location) +">") `
       -nonewline -foregroundcolor Magenta 
     return " "
    }
    
  16. * Get weather (from http://blogs.technet.com/b/heyscriptingguy/)
    function Get-Weather ($city, $country) {
     $URI = "http://www.webservicex.net/globalweather.asmx?wsdl"
     $Proxy = New-WebServiceProxy $URI WebServiceProxy
     $Proxy.GetWeather($city,$country)
    }
    
    Get-Weather "Dayton" "United States"
    Get-Weather "Bermuda" "Bermuda"
  17. The following are PowerShell methods that were described in the context of MP3 files sorter.  Study the differences in syntax very carefully.

    function createOneDummyMP3File($fileName, $album, $artist, $year)
    {
      echo '' > $fileName
      id3tool $fileName -a $album -r $artist -y $year
    }
    
    PowerShell functions list their parameters with $names.
    function createTestMP3Files($dirName) {
        mkdir -force $dirName
        pushd $dirName
        foreach ($i in 0..9) {
    	foreach ($j in 0..9) {
    	    createOneDummyMP3File song$i$j.mp3 Album$i Artist$j 200$i
    	}
        }
        popd
    }
    

    Exercise:  Discover what the following do:

Lab Experiment

See http://www.cs.wright.edu/~pmateti/Courses/233/Labs/Scripting/ScriptingLab1.htm and http://www.cs.wright.edu/ ~pmateti/ Courses/233/ Labs/ Scripting/ScriptingLab2.html

Acknowledgements

Sarah Gothard

References

  1. PowerShell, CMD, and bash help files, http://ss64.com/ Required visit.
  2. Bruce Payette, Windows PowerShell in Action, Manning Publications, 2007;  576 pp.;  Recommend reading as many chapters as you can.  (i) First few pages of every chapter in Part I, (ii) almost all of Chapter 2, (iii) Section 7.2, and (iv) Sections A.1 and (v) A.2 are  Required Reading.
  3. Windows PowerShell Manual by MicroSoft. http://technet.microsoft.com/en-us/library/ee692944.aspx Recommended visit -- several times.
  4. PowerShell  Slides  Mainly for instructor's use.

Copyright © 2012 Prabhaker Mateti