DEV Community

jeikabu
jeikabu

Posted on • Originally published at rendered-obsolete.github.io on

8 1

PowerShell Crash Course (Part 2)

I’ve remained committed to improving my powershell game. Reaching for it instead of shoddy bat files whenever possible. There’s a bunch of things that didn’t make it into the first post, including a few things that inadvertantly got left out (e.g. copying files, other loops, etc.). So, I updated that post so it covers basic syntax and core command-line functionality. This post covers mostly auxillary features and utility commands.

time/wc

# time; measure duration of command
Measure-Command { make }
# ls -1; count files in directory
Get-ChildItem | Measure-Object
# wc; count number of lines in file
Get-Content ./Cargo.toml | Measure-Object -Line
Enter fullscreen mode Exit fullscreen mode

https://devblogs.microsoft.com/scripting/maximizing-the-power-of-here-string-in-powershell-for-configuration-data/

&&

PowerShell is nice and all, but one of the things I missed most from bash et al. is the ability to chain commands on success/failure like make clean && make.

Thanks to PowerShell Core being open-source, pwsh joins the party as of 7.0.0-preview.5 so you can do things like:

# Create directory and enter it
New-Item -Type Directory blah && Set-Location blah
Enter fullscreen mode Exit fullscreen mode

If you’re using Windows Terminal, preview 1910 (or newer) should auto-detect it. For older releases, V > Settings (or Ctrl+,) to open profiles.json:

{
    "...": "...",
    "profiles" : 
    [
        {
            "...": "...",
            "commandline" : "C:\\Program Files\\PowerShell\\7-preview\\pwsh.exe",
            "name" : "PowerShell Core",
            "...": "...",
        },
    ]
}
Enter fullscreen mode Exit fullscreen mode

For Visual Studio Code, View > Command Palette (Ctrl+Shift+P) and type select default shell. It should present a drop-down list of options including the version you just installed. You may need to restart VS Code to change the current shell.

Opening a new terminal should now display:

PowerShell 7.0.0-preview.5
Copyright (c) Microsoft Corporation. All rights reserved.
Enter fullscreen mode Exit fullscreen mode

Filtering, substrings, grep, awk

When looking for substrings, make sure you use -like not -contains (which is for collections). Contrast:

$string = "windows-2019"
$string -contains '*2019*' # False
$string -like '*2019*' # True
$string -like '2019' # False
$string.Contains('*2019*') # False
$string.Contains('2019') # True

# Get first item of output
Get-ChildItem | select -First 1
Get-ChildItem | Select-Object -First 1
# Get certain properties of output
(Get-ChildItem).FullName
Get-ChildItem | % { $_.FullName }
Get-ChildItem | Select-Object -ExpandProperty FullName

# grep; find text in files
Select-String -Path ./src/*.rs -Pattern 'let'
# Find text in output
(Get-ChildItem).FullName | Select-String Cargo.*

# Split a string
$x = "0 1 2 3"
-split $x
# Split using explicit delimiter
"0,1,2,3" -split ','
# Split and return specific items
(-split $x)[0,-1] # 0 3
(-split $x)[-2..-1] # 2 3
(-split $x)[0,1+2..3] # all
(-split $x)[2..3+0] # 2 3 0
# WARNING: The following DON'T work
(-split $x)[0+2..3]
(-split $x)[0,2..3]
(-split $x)[2..3,0]
Enter fullscreen mode Exit fullscreen mode

Formatting

# Output certain columns
Get-ChildItem | Format-Table Name, Size
"{1} {0}" -f "A", "B" # B A
"{0:X8}" -f 42 # 0000002A
[String]::Format("{0:x8}", 42) # 0000002a

# Convert to json
Get-ChildItem | Format-Table Name, Size | ConvertTo-Json
# Parse json file and get "tasks" field
(Get-Content ./.vscode/tasks.json | ConvertFrom-Json).tasks
# Parse key-value pairs as hashtable
'{ "key":"value1", "Key":"value2" }' | ConvertFrom-Json -AsHashtable
Enter fullscreen mode Exit fullscreen mode

Aliases/which/whereis

Get-Alias:

# List all aliases
alias
Get-Alias
# Get alias for `Get-Command`
Get-Alias -Definition Get-Command
# Get aliases matching `gc*`
Get-Alias gc*
Get-Alias -Name gc*
Enter fullscreen mode Exit fullscreen mode

which and whereis from this SO:

# All "gcc*" commands
Get-Command gcc*
# As a nicer table
Get-Command gcc* | Format-Table Name, Path
# Full path to first `cargo`
Get-Command cargo | Select-Object -First 1 -ExpandProperty Path
# Execute it
& $(Get-Command cargo | Select-Object -First 1 -ExpandProperty Path)
Enter fullscreen mode Exit fullscreen mode

Profiles

Profiles are scripts that run when PowerShell starts (like .bashrc etc.). $profile is the current profile:

Win10 $home\Documents\PowerShell\Microsoft.PowerShell_profile.ps1
Linux/MacOS $home/.config/powershell/Microsoft.PowerShell_profile.ps1

This is where you can set Set-PSReadLineOption and other environment/session customizations.

More Loops

Get-Alias -Definition "*ForEach*"

CommandType Name Version Source
----------- ---- ------- ------
Alias % -> ForEach-Object
Alias foreach -> ForEach-Object
Enter fullscreen mode Exit fullscreen mode

Repeat something X times:

0..10 | % {
    # Commands to repeat here
}
Enter fullscreen mode Exit fullscreen mode

Archives

Expand-Archive:

# Extract to bundle/
Expand-Archive bundle.zip
# Extract to path
Expand-Archive bundle.zip .
Expand-Archive bundle.zip -DestinationPath .
# Extract multiple files
Get-ChildItem $Home/Downloads -Filter *.zip | Expand-Archive -DestinationPath output/ -Force
Enter fullscreen mode Exit fullscreen mode

If you’ve got something that’s not a zip, perhaps a series of 7zip .7z.001, .002, etc. (from this SO):

& $env:ProgramFiles\7-Zip\7z.exe x .\Downloads\*.7z.* "-o.\Downloads" -y
Enter fullscreen mode Exit fullscreen mode

curl/wget

This blog covers options for downloading files. While BITS via Start-BitsTransfer is a great option for Windows, Invoke-WebRequest works best for multi-platform scripts:

# wget; Http GET
Invoke-WebRequest https://sh.rustup.rs -OutFile rustup-init.sh
Enter fullscreen mode Exit fullscreen mode

Visual Studio

If you use Visual Studio you’re familiar with the “developer command prompt”- a cmd shell to use VS executables from the command line. A recent VS 2019 update came with “Developer PowerShell for VS 2019”:

After launching powershell it initializes the environment with:

Import-Module "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\Tools\Microsoft.VisualStudio.DevShell.dll"
Enter-VsDevShell 20a49f0c
Enter fullscreen mode Exit fullscreen mode

Let’s take a look at Enter-VsDevShell:

PS> Get-Help Enter-VsDevShell

NAME
    Enter-VsDevShell

SYNTAX
    Enter-VsDevShell -VsInstallPath <string> [-SkipExistingEnvironmentVariables] [-StartInPath <string>] [-DevCmdArguments <string>] [-DevCmdDebugLevel {None | Basic | Detailed | Trace}] [-SkipAutomaticLocation] [-SetDefaultWindowTitle] [<CommonParameters>]

    Enter-VsDevShell [-VsInstanceId] <string> [-SkipExistingEnvironmentVariables] [-StartInPath <string>] [-DevCmdArguments <string>] [-DevCmdDebugLevel {None | Basic | Detailed | Trace}] [-SkipAutomaticLocation] [-SetDefaultWindowTitle] [<CommonParameters>]

    Enter-VsDevShell [-Test] [-DevCmdDebugLevel {None | Basic | Detailed | Trace}] [<CommonParameters>]
Enter fullscreen mode Exit fullscreen mode

For example, to get a powershell instance for VS 2019 Community edition:

$vspath = "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\"
Import-Module "$vspath\Common7\Tools\Microsoft.VisualStudio.DevShell.dll"
Enter-VsDevShell -VsInstallPath $vspath
Enter fullscreen mode Exit fullscreen mode

Sentry image

Hands-on debugging session: instrument, monitor, and fix

Join Lazar for a hands-on session where you’ll build it, break it, debug it, and fix it. You’ll set up Sentry, track errors, use Session Replay and Tracing, and leverage some good ol’ AI to find and fix issues fast.

RSVP here →

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs