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.
Next
Next

Understanding Ollama Model Storage and Portability with the Model Manager