DARK
< BACK TO TOOLS
THE HITCHHIKER'S GUIDE
TO THE COMMAND LINE
SURVIVAL EDITION // UBUNTU & POWERSHELL_
"The Guide says there is an art to flying, or rather a knack. The knack lies in learning how to throw yourself at the ground and miss. In much the same way, there is an art to the command line. The knack lies in knowing just enough commands to look like you know what you're doing, while quietly Googling the rest."

— The Hitchhiker's Guide to the Command Line, p.1
01 THE BASICS
"In the beginning was the command prompt, and the command prompt was with the terminal, and the command prompt was the terminal. All things were made through it, and without it was not any server configured that was configured." The Guide notes that most problems in computing stem from people not knowing where they are. The pwd command exists precisely because of this.
CHECK OS VERSION
lsb_release -a
Also: cat /etc/issue.net for a quicker look.
CHECK OS VERSION
Get-ComputerInfo | Select-Object OsName, OsVersion, OsBuildNumber
Or the classic: winver for a GUI pop-up.
SET HOSTNAME
sudo hostnamectl set-hostname <new-hostname>
Takes effect immediately. Reboot to ensure all services pick it up.
SET HOSTNAME
Rename-Computer -NewName "NewName" -Restart
The -Restart flag applies the change immediately on reboot.
WHERE AM I
pwd
Print working directory. Fundamental. Use it constantly.
WHERE AM I
Get-Location
Alias: pwd also works in PowerShell.
MEMORY USAGE
free -h
The -h flag gives human-readable sizes. Focus on Mem row: total vs available.
MEMORY USAGE
Get-CimInstance Win32_OperatingSystem | Select-Object TotalVisibleMemorySize, FreePhysicalMemory
Values are in KB. Divide by 1MB for GB: | ForEach-Object { [math]::Round($_.FreePhysicalMemory/1MB,2) }
CPU INFO
lscpu | egrep 'Model name|Socket|Thread|NUMA|CPU\(s\)'
Full output: lscpu
CPU INFO
Get-CimInstance Win32_Processor | Select-Object Name, NumberOfCores, NumberOfLogicalProcessors
LIVE RESOURCE MONITOR
htop
Install first: sudo apt install htop. The classic top works without install. Press h for help inside either.
LIVE RESOURCE MONITOR
Get-Process | Sort-Object CPU -Descending | Select-Object -First 20 Name, CPU, WorkingSet
For continuous update: wrap in while($true){ cls; ...; Start-Sleep 2 }
02 FILE MANAGEMENT
The Guide describes file management as "the art of knowing where you put things, as opposed to the more common skill of knowing where you lost them." It goes on to note that the rm -rf / command is the digital equivalent of the Ravenous Bugblatter Beast of Traal: it assumes that if you can't see it any more, neither can anyone else.
LIST FILES
ls -lah
-l long format, -a show hidden, -h human-readable sizes.
LIST FILES
Get-ChildItem -Force
Alias: ls or dir. -Force shows hidden files.
COPY FILE
sudo cp /source/file /dest/file
Add -r to copy directories recursively.
COPY FILE
Copy-Item "C:\source\file.txt" -Destination "C:\dest\"
Add -Recurse for directories.
MOVE / RENAME FILE
sudo mv /source/file /destination/
Works for renaming too — just change the destination filename.
MOVE / RENAME FILE
Move-Item "C:\source\file.txt" -Destination "C:\dest\"
Rename: change the destination to a new filename.
DELETE FILE
sudo rm /path/to/file
Directories: rm -r /path/to/dir. There is no undo. The Guide recommends caution.
DELETE FILE
Remove-Item "C:\path\to\file.txt"
Directories: add -Recurse. Add -WhatIf to preview before deleting.
CREATE DIRECTORY
sudo mkdir -p /path/to/new/dir
-p creates parent directories as needed, no error if exists.
CREATE DIRECTORY
New-Item -ItemType Directory -Path "C:\new\folder" -Force
-Force suppresses the error if it already exists.
FIND FILES
find /path -name "*.log" -type f
Search within files: grep -r "search term" /path
FIND FILES
Get-ChildItem -Path "C:\" -Filter "*.log" -Recurse -ErrorAction SilentlyContinue
Search within files: Select-String -Path "*.log" -Pattern "term"
COPY FILE TO REMOTE SERVER
scp /local/file user@host:/remote/path/
Reverse for pulling: put remote path first, local second.
COPY FILE TO REMOTE SERVER
Copy-Item "C:\local\file.txt" -Destination "\\server\share\"
For SSH/SCP: scp works in PowerShell if OpenSSH is installed.
EXTRACT TAR ARCHIVE
sudo tar -jxf /path/file.tar.bz2 --directory /destination/
Flags: -j bz2, -z gzip, -x extract, -f filename. For .gz: replace -j with -z.
EXTRACT ZIP ARCHIVE
Expand-Archive -Path "C:\file.zip" -DestinationPath "C:\dest\"
Create zip: Compress-Archive -Path "C:\folder" -DestinationPath "C:\out.zip"
03 DISK MANAGEMENT
The Guide's entry on disk management runs to several thousand pages and is generally considered one of the most depressing things ever written. The abridged version simply says: "Disks fill up. They always fill up. The only question is whether you notice before or after something important stops working."
CHECK DISK SPACE
df -h
For interactive navigation: sudo ncdu / (install: sudo apt install ncdu)
CHECK DISK SPACE
Get-PSDrive -PSProvider FileSystem | Select-Object Name, @{N='Used(GB)';E={[math]::Round($_.Used/1GB,2)}}, @{N='Free(GB)';E={[math]::Round($_.Free/1GB,2)}}
LIST BLOCK DEVICES / DISKS
lsblk
For detailed partition info: sudo fdisk -l
LIST DISKS
Get-Disk
Partitions: Get-Partition. Volumes: Get-Volume
MOUNT A DISK
sudo mount /dev/sdb1 /mnt/data
Unmount: sudo umount /mnt/data. Persist across reboots by adding to /etc/fstab.
ASSIGN DRIVE LETTER
Set-Partition -DiskNumber 1 -PartitionNumber 1 -NewDriveLetter E
EXTEND LVM LOGICAL VOLUME
sudo lvextend -L +10G /dev/ubuntu-vg/ubuntu-lv sudo resize2fs /dev/ubuntu-vg/ubuntu-lv
Check current state first: sudo vgdisplay and sudo lvdisplay
EXTEND PARTITION
$part = Get-Partition -DriveLetter C $max = ($part | Get-PartitionSupportedSize).SizeMax Resize-Partition -DriveLetter C -Size $max
Extends to maximum available space. Check disk has unallocated space first.
FORMAT PARTITION
sudo mkfs.ext4 /dev/sdb1
Other formats: mkfs.xfs, mkfs.fat. This destroys all data on the partition.
FORMAT PARTITION
Format-Volume -DriveLetter E -FileSystem NTFS -NewFileSystemLabel "DataDrive" -Confirm:$false
FileSystem options: NTFS, FAT32, exFAT, ReFS.
04 NETWORKING
"The Internet," the Guide notes, "is very large and very complicated and most of it doesn't work properly most of the time. The rest of it works perfectly but nobody can remember the commands. This section is for the latter group."
SHOW NETWORK INTERFACES
ip addr show
Short form: ip a. Legacy: ifconfig (install: sudo apt install net-tools)
SHOW NETWORK INTERFACES
Get-NetIPAddress | Select-Object InterfaceAlias, IPAddress, PrefixLength, AddressFamily
All adapters: Get-NetAdapter
TEST CONNECTIVITY
ping -c 4 8.8.8.8
-c 4 sends 4 packets then stops. Without it, pings forever. Ctrl+C to quit.
TEST CONNECTIVITY
Test-NetConnection -ComputerName 8.8.8.8 -InformationLevel Detailed
Test specific port: add -Port 443. Classic ping: ping hostname also works.
CHECK OPEN PORTS
ss -tulnp
Flags: -t TCP, -u UDP, -l listening, -n numeric, -p show process. Legacy: netstat -tulnp
CHECK OPEN PORTS
Get-NetTCPConnection -State Listen | Select-Object LocalAddress, LocalPort, OwningProcess | Sort-Object LocalPort
Map PIDs to process names: Get-Process -Id (Get-NetTCPConnection -State Listen).OwningProcess
ROUTING TABLE
ip route show
Default gateway is the default via line.
ROUTING TABLE
Get-NetRoute | Where-Object DestinationPrefix -eq '0.0.0.0/0'
Full table: Get-NetRoute
DNS LOOKUP
dig example.com
Quick: nslookup example.com. Reverse lookup: dig -x 8.8.8.8
DNS LOOKUP
Resolve-DnsName example.com
Specific record type: Resolve-DnsName example.com -Type MX
TRACE NETWORK PATH
traceroute 8.8.8.8
Install if missing: sudo apt install traceroute. MTR combines ping+traceroute: mtr 8.8.8.8
TRACE NETWORK PATH
Test-NetConnection 8.8.8.8 -TraceRoute
Classic: tracert 8.8.8.8 also works in PowerShell.
05 PROCESSES & SERVICES
The Guide observes that processes are like houseguests: they arrive unannounced, consume your resources, occasionally crash the party, and are very difficult to remove once established. The kill command exists for this reason. Its name is, the Guide notes, admirably honest.
LIST RUNNING PROCESSES
ps aux
Filter by name: ps aux | grep nginx
LIST RUNNING PROCESSES
Get-Process | Sort-Object CPU -Descending
Filter: Get-Process -Name chrome
KILL A PROCESS
kill PID
Find PID first: pgrep processname. Force kill: kill -9 PID. By name: pkill name
KILL A PROCESS
Stop-Process -Name "chrome" -Force
By PID: Stop-Process -Id 1234 -Force
LIST SERVICES
systemctl list-units --type=service --state=running
Failed services: systemctl list-units --state=failed
LIST SERVICES
Get-Service | Where-Object Status -eq 'Running'
All services: Get-Service
START / STOP / RESTART SERVICE
sudo systemctl start nginx sudo systemctl stop nginx sudo systemctl restart nginx sudo systemctl status nginx
Enable at boot: sudo systemctl enable nginx
START / STOP / RESTART SERVICE
Start-Service -Name "wuauserv" Stop-Service -Name "wuauserv" Restart-Service -Name "wuauserv"
Set startup type: Set-Service -Name "wuauserv" -StartupType Automatic
SCHEDULE A TASK (CRON)
crontab -e
Format: MIN HOUR DAY MON DOW command. Example — run daily at 2am: 0 2 * * * /path/script.sh
SCHEDULE A TASK
$action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "C:\script.ps1" $trigger = New-ScheduledTaskTrigger -Daily -At "02:00" Register-ScheduledTask -Action $action -Trigger $trigger -TaskName "MyTask"
06 USER MANAGEMENT
"The concept of user accounts," the Guide explains, "was invented to give system administrators something to blame when things go wrong. Before user accounts, it was always the computer's fault. Now it is always the user's. This represents significant progress."
ADD USER
sudo adduser username
Follows interactive prompts. useradd is the lower-level version — less friendly, more scriptable.
ADD LOCAL USER
$pass = ConvertTo-SecureString "P@ssw0rd" -AsPlainText -Force New-LocalUser -Name "username" -Password $pass -FullName "Full Name"
Add to group: Add-LocalGroupMember -Group "Administrators" -Member "username"
CHANGE USER PASSWORD
sudo passwd username
Omit username to change your own password.
CHANGE USER PASSWORD
$pass = ConvertTo-SecureString "NewP@ss" -AsPlainText -Force Set-LocalUser -Name "username" -Password $pass
GRANT SUDO PRIVILEGES
sudo usermod -aG sudo username
Verify group membership: groups username
ADD USER TO ADMIN GROUP
Add-LocalGroupMember -Group "Administrators" -Member "username"
WHO IS LOGGED IN
w
Also: who or last for login history.
WHO IS LOGGED IN
Get-CimInstance Win32_LoggedOnUser | Select-Object -ExpandProperty Antecedent
Remote sessions: query session /server:hostname
07 FIREWALL
"A firewall," says the Guide, "is a system for ensuring that the right people cannot get in and the wrong people cannot get out. In practice, it mainly ensures that legitimate administrators cannot remember which rules they set, or why, or when." The Guide recommends writing things down. Nobody ever does.
UFW STATUS & ENABLE
sudo ufw status verbose sudo ufw enable
Always allow SSH before enabling: sudo ufw allow ssh. Disable: sudo ufw disable
FIREWALL STATUS
Get-NetFirewallProfile | Select-Object Name, Enabled
Enable all profiles: Set-NetFirewallProfile -All -Enabled True
ALLOW PORT
sudo ufw allow 443/tcp sudo ufw allow from 192.168.1.0/24 to any port 22
Deny: replace allow with deny. List rules with numbers: sudo ufw status numbered
ALLOW PORT
New-NetFirewallRule -DisplayName "Allow HTTPS" -Direction Inbound -Protocol TCP -LocalPort 443 -Action Allow
Remove rule: Remove-NetFirewallRule -DisplayName "Allow HTTPS"
LIST IPTABLES RULES
sudo iptables -L -n -v --line-numbers
Save rules: sudo iptables-save > /etc/iptables/rules.v4
LIST FIREWALL RULES
Get-NetFirewallRule | Where-Object Enabled -eq 'True' | Select-Object DisplayName, Direction, Action | Sort-Object Direction
08 PACKAGE MANAGEMENT
Installing software, the Guide notes, has historically been one of the most dangerous activities available to humans with access to a terminal. Modern package managers have made it considerably safer, though they retain a certain talent for installing seventeen things you didn't ask for alongside the one thing you did.
UPDATE PACKAGE LIST & UPGRADE
sudo apt update && sudo apt upgrade -y
apt update refreshes the package index. apt upgrade installs updates. Always run update before upgrade.
UPDATE PACKAGES
winget upgrade --all
PowerShell modules: Update-Module. Windows Update: Install-Module PSWindowsUpdate; Get-WindowsUpdate -Install
INSTALL PACKAGE
sudo apt install package-name
Install .deb file: sudo dpkg -i file.deb. Search: apt search term
INSTALL PACKAGE
winget install package-name
PowerShell module: Install-Module ModuleName -Scope CurrentUser. Search: winget search term
REMOVE PACKAGE
sudo apt remove package-name sudo apt purge package-name
remove keeps config files. purge removes everything. Clean up orphans: sudo apt autoremove
REMOVE PACKAGE
winget uninstall package-name
Module: Uninstall-Module ModuleName

> Commands verified for Ubuntu 20.04+ and PowerShell 7+.
> Always test in a non-production environment. The Guide accepts no liability for data loss, existential crises, or rogue processes.
> reason42/tools — free, open, no tracking_

∙ cookieless analytics via cloudflare — no cookies, no fingerprinting, no third-party tracking ∙