Add bash style commands to the Windows PowerShell
As a developer that spends 99% of my time on Linux, doing things on Windows gets cumbersome trying to remember the PowerShell syntax. Here’s an easy way to add the most common bash commands to the PowerShell.
Create the file ‘bash-style-commands.ps1’ in your $HOME directory. Open PowerShell and copy/paste the following:
New-Item -Path "$HOME\bash-style-commands.ps1" -ItemType "file" -Force
To open the file in notepad:
notepad $HOME/bash-style-commands.ps1
In notepad, paste the following and save.
# Bash-style commands for PowerShell # Claude 3.7 & Eric Hammond # Usage: Add '. $HOME\bash-style-commands.ps1' to your PowerShell profile # Basic Linux commands Set-Alias -Name ls -Value Get-ChildItem -Option AllScope Set-Alias -Name ll -Value Get-ChildItem -Option AllScope Set-Alias -Name la -Value Get-ChildItem -Option AllScope Set-Alias -Name cat -Value Get-Content -Option AllScope Set-Alias -Name cp -Value Copy-Item -Option AllScope Set-Alias -Name mv -Value Move-Item -Option AllScope Set-Alias -Name rm -Value Remove-Item -Option AllScope Set-Alias -Name grep -Value Select-String -Option AllScope Set-Alias -Name which -Value Get-Command -Option AllScope Set-Alias -Name touch -Value New-Item -Option AllScope Set-Alias -Name clear -Value Clear-Host -Option AllScope Set-Alias -Name pwd -Value Get-Location -Option AllScope Set-Alias -Name df -Value Get-PSDrive -Option AllScope Set-Alias -Name history -Value Get-History -Option AllScope Set-Alias -Name ps -Value Get-Process -Option AllScope Set-Alias -Name less -Value more -Option AllScope Set-Alias -Name who -Value whoami -Option AllScope # Enhanced linux-like commands function mkdir-p { param([string]$path) New-Item -Path $path -ItemType Directory -Force } Set-Alias -Name mkdir -Value mkdir-p -Option AllScope # Improved ls with colors and formatting (similar to ls -la) function ll-linux { param( [Parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)] [string]$Path = "." ) Get-ChildItem -Path $Path -Force | Format-Table -AutoSize Mode, @{Label="LastWriteTime"; Expression={$_.LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss")}}, Length, @{Label="Name"; Expression={ if ($_.PSIsContainer) { "$($_.Name)/" } elseif ($_.Name -match '\.(exe|bat|cmd)$') { "$($_.Name)*" } else { $_.Name } }} } Set-Alias -Name ll -Value ll-linux -Option AllScope -Force # ls -la equivalent function la-linux { param( [Parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)] [string]$Path = "." ) Get-ChildItem -Path $Path -Force } Set-Alias -Name la -Value la-linux -Option AllScope -Force # grep with context (like grep -A -B) function grep-context { param( [Parameter(Mandatory=$true, Position=0)] [string]$Pattern, [Parameter(ValueFromPipeline=$true)] [string]$InputObject, [Parameter(Position=1)] [string]$Path, [int]$Context = 0 ) if ($Path) { $result = Select-String -Pattern $Pattern -Path $Path -Context $Context,$Context } elseif ($InputObject) { $result = $InputObject | Select-String -Pattern $Pattern -Context $Context,$Context } return $result } Set-Alias -Name grepc -Value grep-context -Option AllScope # touch command that creates or updates file timestamp function touch-linux { param( [Parameter(Mandatory=$true, Position=0)] [string]$Path ) if (Test-Path -Path $Path) { (Get-Item -Path $Path).LastWriteTime = Get-Date } else { New-Item -Path $Path -ItemType File } } Set-Alias -Name touch -Value touch-linux -Option AllScope -Force # head command function head-linux { param( [Parameter(Mandatory=$true, Position=0)] [string]$Path, [Parameter(Position=1)] [int]$Lines = 10 ) Get-Content -Path $Path -TotalCount $Lines } Set-Alias -Name head -Value head-linux -Option AllScope # tail command function tail-linux { param( [Parameter(Mandatory=$true, Position=0)] [string]$Path, [Parameter(Position=1)] [int]$Lines = 10 ) Get-Content -Path $Path -Tail $Lines } Set-Alias -Name tail -Value tail-linux -Option AllScope # find command (simplified) function find-linux { param( [Parameter(Position=0)] [string]$Path = ".", [Parameter(Position=1)] [string]$Pattern = "*" ) Get-ChildItem -Path $Path -Recurse -Filter $Pattern } Set-Alias -Name find -Value find-linux -Option AllScope # chmod (simplified permissions) function chmod-linux { param( [Parameter(Mandatory=$true, Position=0)] [string]$Mode, [Parameter(Mandatory=$true, Position=1)] [string]$Path ) # This is a very simplified version that just toggles read-only if ($Mode -match "^[+]r") { Set-ItemProperty -Path $Path -Name IsReadOnly -Value $false Write-Host "Made $Path writable" } elseif ($Mode -match "^[-]w") { Set-ItemProperty -Path $Path -Name IsReadOnly -Value $true Write-Host "Made $Path read-only" } else { Write-Host "Simplified chmod only supports +r and -w" } } Set-Alias -Name chmod -Value chmod-linux -Option AllScope # wget equivalent function wget-linux { param( [Parameter(Mandatory=$true, Position=0)] [string]$Uri, [Parameter(Position=1)] [string]$OutFile = (Split-Path -Path $Uri -Leaf) ) Invoke-WebRequest -Uri $Uri -OutFile $OutFile Write-Host "Downloaded $Uri to $OutFile" } Set-Alias -Name wget -Value wget-linux -Option AllScope # cd with pushd behavior for easier navigation function cd-linux { param( [Parameter(Position=0)] [string]$Path = "~" ) if ($Path -eq "-") { # cd - to go back to previous directory $previousPath = (Get-Location -Stack).Path if ($previousPath) { Pop-Location Get-Location } else { Write-Host "No previous directory" } } else { Push-Location -Path $Path -StackName "CD_HISTORY" Get-Location } } Set-Alias -Name cd -Value cd-linux -Option AllScope -Force # A function to go back in directory history function cd-back { param( [int]$Steps = 1 ) for ($i = 0; $i -lt $Steps; $i++) { if ((Get-Location -Stack -StackName "CD_HISTORY").Count -gt 0) { Pop-Location -StackName "CD_HISTORY" } else { Write-Host "Cannot go back further" break } } Get-Location } Set-Alias -Name back -Value cd-back -Option AllScope # A simple 'clear terminal history' command function clear-history { Clear-History Write-Host "Command history cleared!" } Set-Alias -Name ch -Value clear-history -Option AllScope # Shorthand for navigating up directories function cd-up { param( [int]$Levels = 1 ) $path = (Get-Location).Path for ($i = 0; $i -lt $Levels; $i++) { $path = Split-Path -Path $path -Parent } Set-Location -Path $path Get-Location } Set-Alias -Name ".." -Value cd-up -Option AllScope # For multiple levels, use: .. 2 or .. 3 # Environment variable echo like in bash function echo-env { param( [Parameter(Mandatory=$true, Position=0)] [string]$Name ) $varName = $Name -replace '^\$' $value = (Get-Item -Path "Env:$varName" -ErrorAction SilentlyContinue).Value if ($value) { Write-Output $value } else { Write-Host "Environment variable $varName not found" } } Set-Alias -Name echoe -Value echo-env -Option AllScope # Print welcome message when this script is loaded Write-Host "Bash-style commands loaded! You now have Linux-like commands in PowerShell." -ForegroundColor Green Write-Host "Type 'bash-help' for a list of available commands." -ForegroundColor Cyan # Help function to show available Linux-style commands function bash-help { Write-Host "Available Bash-style commands:" -ForegroundColor Cyan Write-Host "--------------------------------" -ForegroundColor Cyan Write-Host "ls, ll, la - List directory contents (with different formatting options)" Write-Host "cat - Display file contents" Write-Host "cp - Copy files or directories" Write-Host "mv - Move or rename files or directories" Write-Host "rm - Remove files or directories" Write-Host "grep, grepc - Search for patterns (grepc adds context lines)" Write-Host "which - Show the full path of commands" Write-Host "touch - Create new files or update timestamps" Write-Host "clear - Clear the terminal screen" Write-Host "pwd - Show current directory" Write-Host "head - Show first N lines of a file" Write-Host "tail - Show last N lines of a file" Write-Host "find - Search for files in a directory hierarchy" Write-Host "chmod - Change file permissions (simplified +r/-w only)" Write-Host "wget - Download files from the web" Write-Host "cd - Change directory with history (cd - to go back)" Write-Host "back - Go back in directory history" Write-Host ".. - Go up one or more directory levels (.. 2 for two levels)" Write-Host "echoe - Echo environment variables (e.g., echoe PATH)" Write-Host "ch - Clear command history" Write-Host "bash-help - Show this help message" Write-Host "" Write-Host "Note: These commands are simplified emulations of Linux commands." -ForegroundColor Yellow Write-Host " Some features may work differently from their Linux counterparts." -ForegroundColor Yellow }
Next, open your PowerShell $PROFILE in notepad:
notepad $PROFILE
Add this line at the end of your profile file and save:
. $HOME\bash-style-commands.ps1
Restart PowerShell, and you should see:
Windows PowerShell Copyright (C) Microsoft Corporation. All rights reserved. Bash-style commands loaded! You now have Linux-like commands in PowerShell. Type 'bash-help' for a list of available commands. C:\Users\user> bash-help Available Bash-style commands: -------------------------------- ls, ll, la - List directory contents (with different formatting options) cat - Display file contents cp - Copy files or directories mv - Move or rename files or directories rm - Remove files or directories grep, grepc - Search for patterns (grepc adds context lines) which - Show the full path of commands touch - Create new files or update timestamps clear - Clear the terminal screen pwd - Show current directory head - Show first N lines of a file tail - Show last N lines of a file find - Search for files in a directory hierarchy chmod - Change file permissions (simplified +r/-w only) wget - Download files from the web cd - Change directory with history (cd - to go back) back - Go back in directory history .. - Go up one or more directory levels (.. 2 for two levels) echoe - Echo environment variables (e.g., echoe PATH) ch - Clear command history bash-help - Show this help message Note: These commands are simplified emulations of Linux commands. Some features may work differently from their Linux counterparts.