Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are some of the most useful yet little known features in the PowerShell language [closed]

Tags:

powershell

People also ask

What does :: mean in PowerShell?

Static member operator :: To find the static properties and methods of an object, use the Static parameter of the Get-Member cmdlet. The member name may be an expression. PowerShell Copy.

How do you use variables in PowerShell?

Working with variablesTo create a new variable, use an assignment statement to assign a value to the variable. You don't have to declare the variable before using it. The default value of all variables is $null . To get a list of all the variables in your PowerShell session, type Get-Variable .


The $$ command. I often have to do repeated operations on the same file path. For instance check out a file and then open it up in VIM. The $$ feature makes this trivial

PS> tf edit some\really\long\file\path.cpp
PS> gvim $$

It's short and simple but it saves a lot of time.


By far the most powerful feature of PowerShell is its ScriptBlock support. The fact that you can so concisely pass around what are effectively anonymous methods without any type constraints are about as powerful as C++ function pointers and as easy as C# or F# lambdas.

I mean how cool is it that using ScriptBlocks you can implement a "using" statement (which PowerShell doesn't have inherently). Or, pre-v2 you could even implement try-catch-finally.

function Using([Object]$Resource,[ScriptBlock]$Script) {
    try {
        &$Script
    }
    finally {
        if ($Resource -is [IDisposable]) { $Resource.Dispose() }
    }
}

Using ($File = [IO.File]::CreateText("$PWD\blah.txt")) {
   $File.WriteLine(...)
}

How cool is that!


A feature that I find is often overlooked is the ability to pass a file to a switch statement.

Switch will iterate through the lines and match against strings (or regular expressions with the -regex parameter), content of variables, numbers, or the line can be passed into an expression to be evaluated as $true or $false

switch -file 'C:\test.txt' 
{   
  'sometext' {Do-Something}   
  $pwd {Do-SomethingElse}  
  42 {Write-Host "That's the answer."}  
  {Test-Path $_} {Do-AThirdThing}  
  default {'Nothing else matched'} 
}

$OFS - output field separator. A handy way to specify how array elements are separated when rendered to a string:

PS> $OFS = ', '
PS> "$(1..5)"
1, 2, 3, 4, 5
PS> $OFS = ';'
PS> "$(1..5)"
1;2;3;4;5
PS> $OFS = $null # set back to default
PS> "$(1..5)"
1 2 3 4 5

Always guaranteeing you get an array result. Consider this code:

PS> $files = dir *.iMayNotExist
PS> $files.length

$files in this case may be $null, a scalar value or an array of values. $files.length isn't going to give you the number of files found for $null or for a single file. In the single file case, you will get the file's size!! Whenever I'm not sure how much data I'll get back I always enclose the command in an array subexpression like so:

PS> $files = @(dir *.iMayNotExist)
PS> $files.length # always returns number of files in array

Then $files will always be an array. It may be empty or have only a single element in it but it will be an array. This makes reasoning with the result much simpler.

Array covariance support:

PS> $arr = '127.0.0.1','192.168.1.100','192.168.1.101'
PS> $ips = [system.net.ipaddress[]]$arr
PS> $ips | ft IPAddressToString, AddressFamily -auto

IPAddressToString AddressFamily
----------------- -------------
127.0.0.1          InterNetwork
192.168.1.100      InterNetwork
192.168.1.101      InterNetwork

Comparing arrays using Compare-Object:

PS> $preamble = [System.Text.Encoding]::UTF8.GetPreamble()
PS> $preamble | foreach {"0x{0:X2}" -f $_}
0xEF
0xBB
0xBF
PS> $fileHeader = Get-Content Utf8File.txt -Enc byte -Total 3
PS> $fileheader | foreach {"0x{0:X2}" -f $_}
0xEF
0xBB
0xBF
PS> @(Compare-Object $preamble $fileHeader -sync 0).Length -eq 0
True

Fore more stuff like this, check out my free eBook - Effective PowerShell.


Along the lines of multi-variable assignments.

$list = 1,2,3,4

While($list) {
$head, $list = $list
$head
}

1
2
3
4