Your First Script

A script is a .ps1 file of commands that run from top to bottom, with comments starting with # that say what it does, and you run it from its own folder with .\ and its name, because PowerShell never looks in the current folder for a command on its own.

Apprentice · PowerShell · Updated

After this lesson you can

  • Write a .ps1 script of commands that run from top to bottom, with comments that say what it does
  • Run a script from its own folder with .\ and its name, and explain why PowerShell needs the .\

Key takeaways

  • A script is a .ps1 text file of commands. Running it runs them from top to bottom, like steps in a recipe.
  • A line starting with # is a comment, a note for people that PowerShell skips. <# and #> wrap a comment of many lines.
  • Run a script in the folder you're in with .\ and its name, read "dot backslash": .\morning.ps1.
  • PowerShell never looks in the current folder for a command on its own, so a file there can't stand in for a command you meant. .\ says you mean this file.

Every morning this week you've opened PowerShell and typed the same things: a greeting to yourself, the date, your to-do list, and a check that drive C: isn't filling up. Four small jobs, every single day, and on the busy mornings you skip the drive check and forget it for a month. Put the commands in a file, and one name does them all, in order, every time. That file is your first script, and it's how every automation people get paid for starts.

Make a practice folder with a to-do list in it. These lines are safe to run again:

New-Item -ItemType Directory -Force -Path "$HOME\terminal-practice\morning" | Out-Null
Set-Location "$HOME\terminal-practice\morning"
Set-Content -Path todo.txt -Value 'Pay the phone bill', 'Finish the history essay', 'Buy coffee beans'

One new command: Get-PSDrive

Get-PSDrive gets a drive, as an object (What an Object Is: Get-Member). Its Free property is the free space in bytes, a number too long to read, so divide it by 1GB, PowerShell's word for one gigabyte:

(Get-PSDrive -Name C).Free / 1GB
805.812465667725

Your number is your own drive's. [math]::Round( , 1), from Columns You Make Yourself: Calculated Properties, cuts it to one decimal place. On a Mac or Linux, the drive is called /, not C.

A file of commands

Open a new file with code morning.ps1 (Writing Scripts in VS Code) or edit morning.ps1 (Editing in the Terminal: edit), type these lines, and save:

# morning.ps1: my start-of-the-day check.
# Greets me, then shows the date, my to-do list and the free space on drive C.

Write-Output "Good morning, $env:USERNAME!"
Write-Output "Today is $(Get-Date -Format 'dddd, MMMM d')."

Write-Output ''
Write-Output 'To do:'
Get-Content -Path todo.txt

Write-Output ''
$drive = Get-PSDrive -Name C
Write-Output "Free space on C: $([math]::Round($drive.Free / 1GB, 1)) GB"

Every line is a command you could type at the prompt. $env:USERNAME is the environment variable that holds your user name (Environment Variables and PATH), $( ) puts a command's answer into text (Text: Quotes and $( )), and Write-Output '' prints an empty line to space the output out. A script runs its lines from top to bottom, the way a cook follows a recipe, and $drive, set on one line, is there for the lines after it.

The .ps1 at the end of the name is what makes it a PowerShell script: it tells PowerShell, VS Code and Windows what kind of file it is.

Comments: notes for people

The first two lines start with # (read "hash"), which makes them comments: notes for people, which PowerShell skips. Write at least one at the top of every script, saying what it does. In three months, Greets me, then shows the date, my to-do list and the free space on drive C. saves you reading every line.

A comment can also go at the end of a line, after the command: $drive = Get-PSDrive -Name C # the drive Windows is on. For a note of many lines, put <# (read "comment start") before it and #> ("comment end") after it:

<#
morning.ps1: my start-of-the-day check.
Next: add the weather.
#>

Run it: .\ and its name

Try to run it by its name, the way you run a command:

morning.ps1
morning.ps1: The term 'morning.ps1' is not recognized as a name of a cmdlet, function, script file, or executable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.

[General Feedback]
  The command "morning.ps1" was not found, but does exist in the current location.
  PowerShell does not load commands from the current location by default (see 'Get-Help about_Command_Precedence').

  If you trust this command, run the following command instead:
    ➤ .\morning.ps1

PowerShell found no command called morning.ps1, even though the file is right there, and its feedback says why: it never looks in the current folder, the folder you're in, when you type a name. It looks only at its own commands and at the folders on your PATH.

That's on purpose. Windows' old Command Prompt looks in the current folder first, so a file called notepad.bat in a folder you downloaded would run instead of Notepad when you typed notepad there. In PowerShell, a file in the folder you're in can never stand in for a command you meant. When you do want that file, you say so, with .\ (read "dot backslash": this folder, then this file):

.\morning.ps1
Good morning, Sam!
Today is Monday, November 9.

To do:
Pay the phone bill
Finish the history essay
Buy coffee beans

Free space on C: 805.8 GB

That's your first application, running. Yours shows your own name, today's date and your own drive. Tab helps here too: type .\mo and press Tab.

If PowerShell says the script cannot be loaded instead, Why a Script Won't Run: The Execution Policy explains the fix; in Windows PowerShell 5.1, scripts are switched off at first. On a Mac or Linux, ./morning.ps1 works the same way.

Try it in the terminal

Terminal Quest: Mission Control, goal 1: played right on the lesson page.

Launch day at Mission Control, and the flight director wants scripts, not clicks. Read her briefing: it lists the jobs your scripts will do, and how they'll be run, with .\ and their names.

Check yourself

2 questions to try on the lesson page.

So what

A comment, a few commands and .\ with the name: that's a whole application. Every script you write from now on, however big, starts exactly like this one.

Key terms

Cheat sheets

Related