A comprehensive comparison between PowerShell and Linux/bash commands for system administrators working across platforms.
| Aspect | PowerShell | Linux/Bash |
|--------|------------|------------|
| Data Type | Works with objects | Works with text streams |
| Output | Structured objects | Plain text |
| Approach | Verb-Noun commands | Short cryptic commands |
| Case Sensitivity | Case insensitive | Case sensitive |
| Help System | Built-in comprehensive help | Man pages + various docs |
---
| Task | PowerShell | Linux |
|------|------------|--------|
| Current directory | Get-Location
or pwd
| pwd
|
| Change directory | Set-Location C:\temp
or cd C:\temp
| cd /tmp
|
| List files | Get-ChildItem
or ls
or dir
| ls
|
| List with details | Get-ChildItem -Force
| ls -la
|
| List recursively | Get-ChildItem -Recurse
| find .
or ls -R
|
# PowerShell
Get-ChildItem -Path C:\temp -Recurse -Force | Where-Object {$_.Extension -eq ".txt"}
# Linux equivalent
find /tmp -name "*.txt" -type f
| Task | PowerShell | Linux |
|------|------------|--------|
| Create directory | New-Item -Type Directory -Path C:\folder
| mkdir /folder
|
| Create file | New-Item -Type File -Path C:\file.txt
| touch /file.txt
|
| Copy file | Copy-Item source.txt dest.txt
| cp source.txt dest.txt
|
| Copy directory | Copy-Item -Recurse C:\src C:\dest
| cp -r /src /dest
|
| Move/rename | Move-Item old.txt new.txt
| mv old.txt new.txt
|
| Delete file | Remove-Item file.txt
| rm file.txt
|
| Delete directory | Remove-Item -Recurse -Force folder
| rm -rf folder
|
# PowerShell - Copy all .txt files
Get-ChildItem *.txt | Copy-Item -Destination C:\backup
# Linux equivalent
cp *.txt /backup/
---
| Task | PowerShell | Linux |
|------|------------|--------|
| Display file | Get-Content file.txt
| cat file.txt
|
| First 10 lines | Get-Content file.txt -TotalCount 10
| head file.txt
|
| Last 10 lines | Get-Content file.txt -Tail 10
| tail file.txt
|
| Follow/monitor | Get-Content file.txt -Wait
| tail -f file.txt
|
| Display with line numbers | Get-Content file.txt \| ForEach-Object {$i=1} {"$i
: $_"; $i++} |
cat -n file.txt` |
| Task | PowerShell | Linux |
|------|------------|--------|
| Write to file | "Hello" \| Out-File file.txt
| echo "Hello" > file.txt
|
| Append to file | "Hello" \| Add-Content file.txt
| echo "Hello" >> file.txt
|
| Write multiple lines | @("Line1","Line2") \| Out-File file.txt
| printf "Line1\nLine2\n" > file.txt
|
| Task | PowerShell | Linux |
|------|------------|--------|
| Search in files | Select-String "pattern" .txt
| grep "pattern" .txt
|
| Case insensitive search | Select-String "pattern" .txt
| grep -i "pattern" .txt
|
| Count lines | (Get-Content file.txt).Count
| wc -l file.txt
|
| Sort lines | Get-Content file.txt \| Sort-Object
| sort file.txt
|
| Unique lines | Get-Content file.txt \| Sort-Object -Unique
| sort file.txt \| uniq
|
| Replace text | (Get-Content file.txt) -replace "old","new"
| sed 's/old/new/g' file.txt
|
# PowerShell - Find files containing "error" and show line numbers
Get-ChildItem *.log | Select-String "error" | Select-Object Filename,LineNumber,Line
# Linux equivalent
grep -n "error" *.log
---
| Task | PowerShell | Linux |
|------|------------|--------|
| OS Information | Get-ComputerInfo
| uname -a
|
| Hostname | $env:COMPUTERNAME
| hostname
|
| Current user | $env:USERNAME
| whoami
|
| Uptime | (Get-CimInstance Win32_OperatingSystem).LastBootUpTime
| uptime
|
| System load | Get-Counter "\Processor(_Total)\% Processor Time"
| top
or htop
|
| Memory usage | Get-CimInstance Win32_OperatingSystem
| free -h
|
| Disk usage | Get-CimInstance Win32_LogicalDisk
| df -h
|
# PowerShell - Memory usage percentage
$os = Get-CimInstance Win32_OperatingSystem
$memUsed = ($os.TotalVisibleMemorySize - $os.FreePhysicalMemory) / $os.TotalVisibleMemorySize * 100
Write-Host "Memory Usage: $([math]::Round($memUsed,1))%"
# Linux equivalent
free | awk 'NR==2{printf "Memory Usage: %.1f%%\n", $3*100/$2}'
---
| Task | PowerShell | Linux |
|------|------------|--------|
| List processes | Get-Process
| ps aux
|
| Find process | Get-Process -Name "notepad"
| ps aux \| grep notepad
|
| Kill process by name | Stop-Process -Name "notepad"
| pkill notepad
|
| Kill process by PID | Stop-Process -Id 1234
| kill 1234
|
| Force kill | Stop-Process -Name "app" -Force
| kill -9 1234
|
| Start process | Start-Process "notepad.exe"
| notepad.exe &
|
| Background process | Start-Job { Start-Process "app.exe" }
| app.exe &
|
# PowerShell - Find processes using most memory
Get-Process | Sort-Object WorkingSet -Descending | Select-Object -First 5 Name,WorkingSet
# Linux equivalent
ps aux --sort=-%mem | head -5
---
| Task | PowerShell | Linux (systemd) |
|------|------------|-----------------|
| List services | Get-Service
| systemctl list-units --type=service
|
| Service status | Get-Service -Name "Spooler"
| systemctl status sshd
|
| Start service | Start-Service -Name "Spooler"
| systemctl start sshd
|
| Stop service | Stop-Service -Name "Spooler"
| systemctl stop sshd
|
| Restart service | Restart-Service -Name "Spooler"
| systemctl restart sshd
|
| Enable at boot | Set-Service -Name "Spooler" -StartupType Automatic
| systemctl enable sshd
|
| Disable at boot | Set-Service -Name "Spooler" -StartupType Disabled
| systemctl disable sshd
|
---
| Task | PowerShell | Linux |
|------|------------|--------|
| Test connectivity | Test-NetConnection google.com
| ping google.com
|
| Test specific port | Test-NetConnection google.com -Port 80
| telnet google.com 80
|
| Show IP config | Get-NetIPAddress
| ip addr show
|
| Show routing table | Get-NetRoute
| ip route show
|
| DNS lookup | Resolve-DnsName google.com
| nslookup google.com
|
| Download file | Invoke-WebRequest url -OutFile file
| wget url
or curl -o file url
|
| Show open ports | Get-NetTCPConnection
| netstat -tuln
|
# PowerShell - Check if multiple servers are reachable
$servers = @("server1", "server2", "server3")
$servers | ForEach-Object {
$result = Test-NetConnection $_ -Port 80 -WarningAction SilentlyContinue
[PSCustomObject]@{Server=$_; Reachable=$result.TcpTestSucceeded}
}
# Linux equivalent
for server in server1 server2 server3; do
if timeout 5 bash -c "</dev/tcp/$server/80"; then
echo "$server: Reachable"
else
echo "$server: Not reachable"
fi
done
---
| Concept | PowerShell | Linux/Bash |
|---------|------------|------------|
| Variable assignment | $name = "John"
| name="John"
|
| Variable access | $name
| $name
|
| Environment variables | $env:PATH
| $PATH
|
| Command substitution | $date = Get-Date
| date=$(date)
|
| Array | $arr = @("a","b","c")
| arr=("a" "b" "c")
|
| Array access | $arr[0]
| ${arr[0]}
|
| Task | PowerShell | Linux |
|------|------------|--------|
| List all env vars | Get-ChildItem env:
| env
or printenv
|
| Get specific var | $env:PATH
| echo $PATH
|
| Set env var | $env:MYVAR = "value"
| export MYVAR="value"
|
| Set permanent var | [Environment]::SetEnvironmentVariable("MYVAR","value","User")
| Add to ~/.bashrc
|
---
PowerShell Script (.ps1)
#!/usr/bin/env pwsh
# Parameters
param(
[string]$ServerName = "localhost",
[int]$Port = 80
)
# Function
function Test-Connection {
param($Server, $Port)
$result = Test-NetConnection $Server -Port $Port
return $result.TcpTestSucceeded
}
# Main logic
if (Test-Connection $ServerName $Port) {
Write-Host "Server $ServerName is reachable on port $Port" -ForegroundColor Green
} else {
Write-Host "Server $ServerName is NOT reachable on port $Port" -ForegroundColor Red
}
Bash Script (.sh)
#!/bin/bash
# Parameters with defaults
SERVER_NAME=${1:-localhost}
PORT=${2:-80}
# Function
test_connection() {
local server=$1
local port=$2
timeout 5 bash -c "</dev/tcp/$server/$port" 2>/dev/null
return $?
}
# Main logic
if test_connection "$SERVER_NAME" "$PORT"; then
echo -e "\033[32mServer $SERVER_NAME is reachable on port $PORT\033[0m"
else
echo -e "\033[31mServer $SERVER_NAME is NOT reachable on port $PORT\033[0m"
fi
PowerShell
if ($age -ge 18) {
Write-Host "Adult"
} elseif ($age -ge 13) {
Write-Host "Teenager"
} else {
Write-Host "Child"
}
# Switch statement
switch ($day) {
"Monday" { "Start of work week" }
"Friday" { "TGIF!" }
default { "Regular day" }
}
Bash
if [ $age -ge 18 ]; then
echo "Adult"
elif [ $age -ge 13 ]; then
echo "Teenager"
else
echo "Child"
fi
# Case statement
case $day in
"Monday") echo "Start of work week" ;;
"Friday") echo "TGIF!" ;;
*) echo "Regular day" ;;
esac
PowerShell
# ForEach
$fruits = @("apple", "banana", "cherry")
foreach ($fruit in $fruits) {
Write-Host "I like $fruit"
}
# For loop
for ($i = 1; $i -le 10; $i++) {
Write-Host "Count: $i"
}
# While loop
$count = 1
while ($count -le 5) {
Write-Host "Count: $count"
$count++
}
Bash
# For loop with array
fruits=("apple" "banana" "cherry")
for fruit in "${fruits[@]}"; do
echo "I like $fruit"
done
# For loop with range
for i in {1..10}; do
echo "Count: $i"
done
# While loop
count=1
while [ $count -le 5 ]; do
echo "Count: $count"
((count++))
done
---
PowerShell
try {
$result = Get-Content "nonexistent.txt"
} catch {
Write-Error "File not found: $($_.Exception.Message)"
} finally {
Write-Host "Cleanup code here"
}
# Check last command success
if ($?) {
Write-Host "Command succeeded"
} else {
Write-Host "Command failed"
}
Bash
# Simple error handling
if ! cp source.txt dest.txt 2>/dev/null; then
echo "Copy failed" >&2
exit 1
fi
# Check exit code
if [ $? -eq 0 ]; then
echo "Command succeeded"
else
echo "Command failed"
fi
# Set error handling
set -e # Exit on any error
set -u # Exit on undefined variable
---
| Task | PowerShell | Linux (Ubuntu/Debian) | Linux (RHEL/CentOS) |
|------|------------|----------------------|-------------------|
| Install package | Install-Module ModuleName
| apt install package
| yum install package
|
| Update packages | Update-Module
| apt update && apt upgrade
| yum update
|
| Search packages | Find-Module keyword
| apt search keyword
| yum search keyword
|
| List installed | Get-InstalledModule
| apt list --installed
| yum list installed
|
| Remove package | Uninstall-Module ModuleName
| apt remove package
| yum remove package
|
---
| Task | PowerShell | Linux |
|------|------------|--------|
| Show permissions | Get-Acl C:\file.txt
| ls -l file.txt
|
| Change permissions | Set-Acl -Path C:\file.txt -AclObject $acl
| chmod 755 file.txt
|
| Change owner | Complex ACL operations | chown user:group file.txt
|
| Task | PowerShell | Linux |
|------|------------|--------|
| Current user | $env:USERNAME
| whoami
|
| List users | Get-LocalUser
| cat /etc/passwd
|
| Add user | New-LocalUser -Name "user"
| useradd user
|
| User groups | Get-LocalGroup
| groups
or id
|
---
# Find large files
Get-ChildItem C:\ -Recurse | Where-Object {$_.Length -gt 100MB} | Sort-Object Length -Descending
# Find files modified in last 7 days
Get-ChildItem -Recurse | Where-Object {$_.LastWriteTime -gt (Get-Date).AddDays(-7)}
# Check disk space on all drives
Get-CimInstance Win32_LogicalDisk | Select-Object DeviceID,@{n='Size(GB)';e={[math]::Round($_.Size/1GB,2)}},@{n='Free(GB)';e={[math]::Round($_.FreeSpace/1GB,2)}}
# Find duplicate files by hash
Get-ChildItem -Recurse | Get-FileHash | Group-Object Hash | Where-Object {$_.Count -gt 1}
# Find large files
find / -type f -size +100M -exec ls -lh {} \; 2>/dev/null | sort -k5 -hr
# Find files modified in last 7 days
find . -type f -mtime -7
# Check disk space
df -h
# Find duplicate files by hash
find . -type f -exec md5sum {} \; | sort | uniq -d -w 32
---
Use PowerShell when:
Use Linux/Bash when:
---
PowerShell Core (6+) runs on Linux too! Install with:
# Ubuntu/Debian
sudo apt install powershell
# RHEL/CentOS
sudo yum install powershell
# Run PowerShell on Linux
pwsh
This gives you PowerShell's object-oriented approach on Linux systems, combining the best of both worlds!