What Is Scripting?
What a script is and when writing one pays off, the difference between Bash and PowerShell, shells and interpreters, and how this topic compares them side by side.
What a script is
A script is a program that an interpreter runs straight from its source text, without a separate compile step. A shell script is the simplest kind: the same commands you type at the prompt, written in a file and run from top to bottom (see Shell Scripting Basics). Shell languages are scripting languages built for one job above all: starting other programs and gluing their results together.
-
A Bash script is a text file of
Bash commands, usually named
something.shand started with a shebang line such as#!/bin/bash, so that Linux knows which program must run it. -
A PowerShell script is a
text file of PowerShell commands with the extension
.ps1. The extension matters: inside PowerShell only a.ps1file runs as a script, and on Windowspwsh -Filealso refuses any other extension.
Here is the same small check in both languages: warn when a disk is above 90% full. The Bash version comes first on every page of this topic, the PowerShell version directly after it.
usage=91
threshold=90
if (( usage > threshold )); then
echo "WARNING: disk at ${usage}%"
fi
WARNING: disk at 91%
$usage = 91
$threshold = 90
if ($usage -gt $threshold) {
"WARNING: disk at $usage%"
}
WARNING: disk at 91%
The shape is the same; the details are not. PowerShell variables
always start with $, also when you assign them, and it
compares numbers with -gt (greater than). A string on
its own line, such as "WARNING: …", is simply output:
PowerShell needs no echo. In Bash,
(( … )) is arithmetic, where > means
greater than.
$usage = 91
if ($usage > 90) {
"WARNING: disk at $usage%"
}
"Files in this folder now:"
Get-ChildItem -Name
Get-Content ./90
Files in this folder now: 90 example.ps1 91
No warning, a stray file named 90 that contains
91, and no error message. Use -gt,
-lt, -eq and their relatives, explained on
Conditions, Tests and Exit Codes.
When a script pays off
A script costs time to write, test and maintain. It earns that time back in four situations, and the service desk and operations work at Kestrel Energy, the fictional Dutch energy supplier used as an example throughout this site, is full of them:
- You repeat it. Amara Okafor on the service desk checks the same three things for every "portal is slow" ticket. Typed, that is five minutes and a chance of skipping a step; scripted, it is one command whose output goes straight into the ticket.
- It must be identical every time. Creating an account, rotating a log or preparing a server should not depend on who does it or how tired they are. A script is a procedure that cannot skip a line.
- It has to run without you. A nightly backup check or a disk alert runs at 03:00 from a scheduler (see Scheduling and Logging), which only works if every step is written down as code.
- It runs on many machines. Tomasz Nowak in the network operations center checks a setting on forty servers; one loop over a list of host names beats forty remote sessions (see Remote Execution).
A rough rule: if you have done a task by hand three times and expect to do it again, script it. Start small, by pasting the commands you used into a file, and improve the script each time you use it.
When to choose something else
Shell scripts are glue. They are excellent at running commands, checking results and moving files, and poor at complex logic, large data structures and calculations. Google's Shell Style Guide puts the limit bluntly: a shell script of more than 100 lines, or one with control flow that is not straightforward, should be rewritten in a more structured language. For Bash, that usually means Python (see the Python topic). PowerShell, with real objects and the whole .NET library behind it, stretches further before that point, but the advice is the same: when a script becomes an application, treat it like one.
And some work is better done with a purpose-built tool: a configuration management tool such as Ansible for keeping many servers in a known state, a CI/CD (continuous integration and continuous delivery) system for builds and deployments. Those tools still run small scripts at their edges, which is one more reason to write good ones.
Shells, interpreters and script hosts
A shell is the program that reads your commands and runs them. It works in two modes.
Interactive and non-interactive
An interactive shell is a
shell that reads commands from a person at a terminal: it shows a
prompt, keeps a history, completes names with Tab, and
loads your personal settings, such as aliases in
~/.bashrc or your PowerShell profile. A shell that runs
a script is non-interactive: no prompt, no history, and in Bash no
~/.bashrc. So a command that works at your prompt can
fail in a script, because it relied on something only your
interactive session had:
cat > report.sh <<'X'
#!/bin/bash
alias ll='ls -l'
ll
X
bash report.sh
echo "exit status: $?"
report.sh: line 3: ll: command not found exit status: 127
Bash does not expand
aliases in a
non-interactive shell, so ll is an unknown command
(status 127). Scripts should use full command names, and they should
not depend on your personal settings at all: a scheduler runs them
as another user, with another environment. PowerShell's equivalent
advice is to write full cmdlet names (Get-ChildItem,
not gci) in scripts, and to start scheduled scripts
with pwsh -NoProfile so that nobody's profile can
change what they do.
The script host
The script host is the program
that reads a script file and runs it: bash for a Bash
script, pwsh (PowerShell 7) or
powershell.exe (Windows PowerShell 5.1) for a
.ps1 file. Both are
interpreters: they read and execute the script line by line, which is why a
typo on line 40 shows up only after lines 1 to 39 have already run.
The shebang line, the execute permission and PowerShell's execution
policy decide how the right host gets started; that is the subject
of
Running Scripts.
Bash and PowerShell compared
Bash (the GNU Bourne-Again SHell) is the standard shell of most Linux distributions and the language of countless installation scripts, container entry points and cron jobs. PowerShell is Microsoft's shell and scripting language, built on .NET; it is the standard tool for administering Windows, Active Directory, Microsoft 365 and Azure, and since PowerShell 7 it also runs on Linux and macOS.
Text versus objects
The deepest difference is what travels between commands. Bash connects separate programs with pipes, and what flows through a pipe is text: lines of characters that the next program has to cut apart again. PowerShell's cmdlets run inside one process and hand each other .NET objects with named properties (see Objects, not text). The same question, "which meter used the most energy?", answered both ways:
cat > readings.csv <<'CSV'
meter,kwh
M-1042,4521
M-1043,312
M-1044,2870
CSV
tail -n +2 readings.csv | sort -t, -k2 -n | tail -n 1
M-1042,4521
@'
meter,kwh
M-1042,4521
M-1043,312
M-1044,2870
'@ | Set-Content readings.csv
$rows = Import-Csv readings.csv
$top = $rows | Sort-Object { [int]$_.kwh } | Select-Object -Last 1
"$($top.meter) used $($top.kwh) kWh"
$rows[0].GetType().Name
M-1042 used 4521 kWh PSCustomObject
The Bash pipeline works on positions in the text: skip line 1 (the
header), split at commas, sort numerically on field 2, keep the last
line. Change the column order in the file and the command silently
sorts the wrong thing. The PowerShell pipeline works on names: each
row is an object with the properties
meter and kwh, taken from the header. The
price is more typing, and one catch: values read from a CSV file are
strings, so the script converts them with [int] to sort
them as numbers.
The Pipeline: Text versus Objects works this difference out in detail.
The main differences at a glance
| Bash | PowerShell | |
|---|---|---|
| Home ground | Linux, macOS, containers, CI jobs | Windows, Active Directory, Microsoft 365, Azure; also Linux and macOS |
| Between commands | Text (bytes and lines) | .NET objects with properties |
| Commands |
Separate programs (grep, sort)
plus builtins
|
Cmdlets named Verb-Noun, plus native programs |
| Variables |
name=value, read as $name;
everything is a string
|
$name = value; typed values (numbers, dates,
objects)
|
| Comparison |
[[ $a -gt 5 ]], (( a > 5 ))
|
$a -gt 5 |
| Case | Case-sensitive everywhere |
Commands, variables and -eq are
case-insensitive
|
| Errors | Exit status per command (0 = success) | Error records; terminating and non-terminating errors |
| Script file |
.sh by convention, shebang, execute permission
|
.ps1 required, execution policy on Windows
|
| Help | man bash, help read |
Get-Help about_Quoting_Rules |
Which one to learn first
Learn the one your systems speak. Linux servers, containers and most
CI pipelines expect Bash (or the plainer POSIX
sh); Windows desktops and servers, Active Directory,
Exchange and Microsoft 365 are administered with PowerShell, and
many of their management modules exist only for PowerShell. In mixed
environments you will read both, which is exactly what the
side-by-side layout of this topic is for. PowerShell 7 runs fine on
Linux and Bash runs on Windows through WSL (Windows Subsystem for
Linux), but scripts are happiest on their home ground; see
Cross-Platform Scripting.
Versions and support
Both languages are actively maintained, and which version you have matters: features and defaults change between releases. The state as of October 2026:
| Version | Status (October 2026) |
|---|---|
| Bash 5.3 |
Current release (5 July 2025). Adds, among other things,
command substitution without a subshell,
${ command; }.
|
| Bash 5.2 | What most Linux servers run: Debian 12 ships 5.2.15 and Debian 13 ships 5.2.37. The examples on these pages run on Bash 5.2 and avoid 5.3-only features. |
| PowerShell 7.6 (LTS) | Long Term Servicing release, released 18 March 2026, supported until 14 November 2028; built on .NET 10. The PowerShell examples on these pages run on 7.6.6. |
| PowerShell 7.5 and 7.4 (LTS) | Both reach end of support on 10 November 2026: upgrade to 7.6. |
| PowerShell 7.7 | In preview; not for production. |
| Windows PowerShell 5.1 | Part of Windows and supported as long as the Windows version it ships with; it receives security fixes but no new features. |
| Windows PowerShell 2.0 |
Removed from Windows 11 version 24H2 and Windows Server 2025
(August and September 2025). Scripts that call
powershell.exe -Version 2 no longer get it.
|
Windows PowerShell 5.1 (powershell.exe) and PowerShell
7 (pwsh.exe) are separate products that install side by
side: installing 7 does not replace 5.1. Most scripts run in both,
but there are differences, and some old Windows-only modules work
only in 5.1. The PowerShell ISE (Integrated Scripting Environment)
is still included with Windows but no longer actively developed;
Microsoft recommends Visual Studio Code with the PowerShell
extension.
Check which version a machine has before you rely on a feature:
echo "Bash major version: ${BASH_VERSINFO[0]}"
Bash major version: 5
"Edition: $($PSVersionTable.PSEdition)"
"Major version: $($PSVersionTable.PSVersion.Major)"
Edition: Core Major version: 7
PSEdition is Core for PowerShell 7 and
Desktop for Windows PowerShell 5.1. At a prompt,
bash --version and $PSVersionTable show
the full details:
bash --version | head -n 1
GNU bash, version 5.2.15(1)-release (aarch64-unknown-linux-gnu)
How this topic works
This topic is about writing scripts, not about the commands themselves. The commands are explained elsewhere, and these pages link there instead of repeating them:
-
Linux & Command Line covers
the shell and its commands: files, permissions,
pipes and redirection,
grepandfind, processes, services and a first Bash script. - Using the Windows Command Line covers PowerShell's basics: cmdlets, objects, the pipeline, aliases and the execution policy.
On every page you will find the same conventions:
- Bash first, PowerShell second, solving the same task, with a sentence on what differs and why. Most pages end a section with a small comparison table.
-
Examples with output are run. Every Bash example
runs in an empty folder with Bash 5.2, every PowerShell example
with PowerShell 7.6 on Linux, and the output shown is what they
really print. Error messages show the script folder as
/home/amara/scripts. PowerShell on Windows behaves the same for everything shown in runnable examples. - Some examples cannot run here: anything that needs a network, another server, administrator rights or Windows-only cmdlets. Those are shown as plain code blocks, with output labeled "illustrative".
-
Kestrel Energy supplies the data: meter readings
in kWh, outage tickets such as INC-20419, servers such as
web01anddb01on documentation IP addresses (192.0.2.x), log files and CSV exports.