Vijay replaces PowerShell with bash
Bash scripting for PowerShell users — same logic, different syntax
By month 2, Vijay was comfortable with Linux day-to-day. But he still switched to his Windows machine for scripting. PowerShell felt natural. Bash felt foreign.
His colleague Meena showed him the translation in one hour.
THE CORE TRANSLATION
PowerShell Bash
Write-Host "Hello" echo "Hello"
$var = "value" var="value" (no $ on left, no spaces)
Write-Host $var echo "$var"
$env:PATH $PATH
Get-Date date
Get-Date -Format "yyyy-MM-dd" date +%Y-%m-%d
Start-Sleep 5 sleep 5
Exit 1 exit 1VARIABLES
PowerShell:
$serverName = "prod-server-01"
$today = (Get-Date).ToString("yyyy-MM-dd")Bash:
serverName="prod-server-01" # no $ on left, no spaces around =
today=$(date +%Y-%m-%d) # $() runs a command and captures output# Reading variables is the same: $variablename
echo "Server: $serverName"IF STATEMENTS
PowerShell:
if ($diskUsage -gt 90) {
Write-Host "CRITICAL"
} elseif ($diskUsage -gt 80) {
Write-Host "WARNING"
} else {
Write-Host "OK"
}Bash:
if [ "$diskUsage" -gt 90 ]; then
echo "CRITICAL"
elif [ "$diskUsage" -gt 80 ]; then
echo "WARNING"
else
echo "OK"
fiNumber comparisons: -gt, -lt, -eq, -ne, -ge, -le
String comparisons: = (equal), != (not equal), -z (empty), -n (not empty)
FOR LOOPS
PowerShell:
foreach ($server in @("web-01", "web-02", "web-03")) {
Test-Connection $server
}Bash:
for server in web-01 web-02 web-03; do
ping -c 1 $server
done# Loop over a range:
PowerShell: 1..10 | ForEach-Object { Write-Host $_ }
Bash: for i in {1..10}; do echo $i; doneFUNCTIONS
PowerShell:
function Check-Disk {
param($mount, $threshold)
return $usage
}Bash:
check_disk() {
local mount=$1 # $1 is first argument
local threshold=$2 # $2 is second argument
local usage
usage=$(df "$mount" | awk 'NR==2{print $5}' | tr -d '%')
echo "$usage" # return by printing, capture with $()
}
result=$(check_disk "/" 85)ERROR HANDLING
PowerShell:
try {
Copy-Item source.txt dest.txt
} catch {
Write-Error "Copy failed"
exit 1
}Bash:
set -euo pipefail # exit on any error - like try around everything# Or handle individually:
if ! cp source.txt dest.txt; then
echo "ERROR: Copy failed" >&2
exit 1
fiA REAL SCRIPT TRANSLATION
PowerShell:
$services = @("nginx", "myapp", "postgresql")
$failed = @()
foreach ($svc in $services) {
if ((Get-Service $svc).Status -ne "Running") {
$failed += $svc
}
}
if ($failed.Count -gt 0) { exit 1 }Bash:
#!/bin/bash
set -euo pipefail
services="nginx myapp postgresql"
failed=""
for svc in $services; do
if systemctl is-active --quiet "$svc"; then
echo "OK: $svc"
else
echo "DOWN: $svc"
failed="$failed $svc"
fi
done
if [ -n "$failed" ]; then
echo "FAILED:$failed"
exit 1
fiSCHEDULED TASKS vs CRON
PowerShell: Register-ScheduledTask with -TriggerAt "06:00"
Linux cron: 0 6 * * * /path/to/script.shPowerShell: -RepetitionInterval (New-TimeSpan -Minutes 15)
Linux cron: */15 * * * * /path/to/script.shcrontab -l # list scheduled tasks (like Get-ScheduledTask)
crontab -e # edit scheduled tasks (like Task Scheduler GUI)Vijay converted his most-used PowerShell scripts to bash over two weekends. By month 3 he was writing bash natively without thinking about PowerShell first.
Bash variables have no spaces around = and you read them with $ — var=value then echo $var
if/elif/else/fi is identical logic to PowerShell if/elseif/else — just different brackets and keywords
set -euo pipefail at the top replaces try/catch — exits cleanly on any error
Functions receive arguments as $1 $2 — there are no named parameters like PowerShell param()
crontab -e replaces Task Scheduler — minute hour day month weekday is the 5-field cron syntax