powershell-shell-detection by josiahsiegel/claude-plugin-marketplace
npx skills add https://github.com/josiahsiegel/claude-plugin-marketplace --skill powershell-shell-detection在 Windows 上区分 PowerShell 与 Git Bash/MSYS2 Shell 的关键指南,包含特定于 Shell 的路径处理方法和兼容性说明。
在 Windows 上工作时,正确识别 Shell 环境对于正确的路径处理和命令执行至关重要。
PSModulePath(最可靠):
# PowerShell detection
if ($env:PSModulePath) {
Write-Host "Running in PowerShell"
# PSModulePath contains 3+ paths separated by semicolons
$env:PSModulePath -split ';'
}
# Check PowerShell version
$PSVersionTable.PSVersion
# Output: 7.5.4 (PowerShell 7) or 5.1.x (Windows PowerShell)
PowerShell 特有变量:
# These only exist in PowerShell
$PSVersionTable # Version info
$PSScriptRoot # Script directory
$PSCommandPath # Script full path
$IsWindows # Platform detection (PS 7+)
$IsLinux # Platform detection (PS 7+)
$IsMacOS # Platform detection (PS 7+)
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
function Get-ShellType {
if ($PSVersionTable) {
return "PowerShell $($PSVersionTable.PSVersion)"
}
elseif ($env:PSModulePath -and ($env:PSModulePath -split ';').Count -ge 3) {
return "PowerShell (detected via PSModulePath)"
}
else {
return "Not PowerShell"
}
}
Get-ShellType
MSYSTEM 环境变量(最可靠):
# Bash detection in Git Bash/MSYS2
if [ -n "$MSYSTEM" ]; then
echo "Running in Git Bash/MSYS2: $MSYSTEM"
fi
# MSYSTEM values:
# MINGW64 - Native Windows 64-bit environment
# MINGW32 - Native Windows 32-bit environment
# MSYS - POSIX-compliant build environment
次要检测方法:
# Using OSTYPE (Bash-specific)
case "$OSTYPE" in
msys*) echo "MSYS/Git Bash" ;;
cygwin*) echo "Cygwin" ;;
linux*) echo "Linux" ;;
darwin*) echo "macOS" ;;
esac
# Using uname (Most portable)
case "$(uname -s)" in
MINGW64*) echo "Git Bash 64-bit" ;;
MINGW32*) echo "Git Bash 32-bit" ;;
MSYS*) echo "MSYS" ;;
CYGWIN*) echo "Cygwin" ;;
Linux*) echo "Linux" ;;
Darwin*) echo "macOS" ;;
esac
| 方面 | PowerShell | Git Bash/MSYS2 |
|---|---|---|
| 环境变量 | $env:VARIABLE | $VARIABLE |
| 路径分隔符 | ;(分号) | :(冒号) |
| 路径风格 | C:\Windows\System32 | /c/Windows/System32 |
| 主目录 | $env:USERPROFILE | $HOME |
| 临时目录 | $env:TEMP | /tmp |
| 命令格式 | Get-ChildItem | ls(原生命令) |
| 别名 | PowerShell cmdlet 别名 | Unix 命令别名 |
PowerShell 路径处理:
# Native Windows paths work directly
$path = "C:\Users\John\Documents"
Test-Path $path # True
# Forward slashes also work in PowerShell 7+
$path = "C:/Users/John/Documents"
Test-Path $path # True
# Use Join-Path for cross-platform compatibility
$configPath = Join-Path -Path $PSScriptRoot -ChildPath "config.json"
# Use [System.IO.Path] for advanced scenarios
$fullPath = [System.IO.Path]::Combine($home, "documents", "file.txt")
Git Bash 路径处理:
# Git Bash uses Unix-style paths
path="/c/Users/John/Documents"
test -d "$path" && echo "Directory exists"
# Automatic path conversion (CAUTION)
# Git Bash converts Unix-style paths to Windows-style
# /c/Users → C:\Users (automatic)
# Arguments starting with / may be converted unexpectedly
# Use cygpath for manual conversion
cygpath -u "C:\path" # → /c/path (Unix format)
cygpath -w "/c/path" # → C:\path (Windows format)
cygpath -m "/c/path" # → C:/path (Mixed format)
Git Bash/MSYS2 在某些场景下会自动转换路径,这可能导致问题:
# Leading forward slash triggers conversion
command /foo # Converts to C:\msys64\foo
# Path lists with colons
export PATH=/foo:/bar # Converts to C:\msys64\foo;C:\msys64\bar
# Arguments after dashes
command --path=/foo # Converts to --path=C:\msys64\foo
# Arguments with equals sign (variable assignments)
VAR=/foo command # NOT converted
# Drive specifiers
command C:/path # NOT converted
# Arguments with semicolons (already Windows format)
command "C:\foo;D:\bar" # NOT converted
# Double slashes (Windows switches)
command //e //s # NOT converted
# Disable ALL conversion (Git Bash)
export MSYS_NO_PATHCONV=1
command /foo # Stays as /foo
# Exclude specific patterns (MSYS2)
export MSYS2_ARG_CONV_EXCL="*" # Exclude everything
export MSYS2_ARG_CONV_EXCL="--dir=;/test" # Specific prefixes
PowerShell 示例场景:
# Azure VM management with Az module
Connect-AzAccount
Get-AzVM -ResourceGroupName "Production" |
Where-Object {$_.PowerState -eq "VM running"} |
Stop-AzVM -Force
Git Bash 示例场景:
# Git workflow with Unix tools
git log --oneline | grep -i "feature" | awk '{print $1}' |
xargs git show --stat
# Detect if running in PowerShell or Git Bash context
function Test-PowerShellContext {
return ($null -ne $PSVersionTable)
}
# Adapt path handling based on context
function Get-CrossPlatformPath {
param([string]$Path)
if (Test-PowerShellContext) {
# PowerShell: Use Join-Path
return (Resolve-Path $Path -ErrorAction SilentlyContinue).Path
}
else {
# Non-PowerShell context
Write-Warning "Not running in PowerShell. Path operations may differ."
return $Path
}
}
# Detect shell environment
detect_shell() {
if [ -n "$MSYSTEM" ]; then
echo "git-bash"
elif [ -n "$PSModulePath" ]; then
echo "powershell"
elif [ -n "$WSL_DISTRO_NAME" ]; then
echo "wsl"
else
echo "unix"
fi
}
# Adapt path handling
convert_path() {
local path="$1"
local shell_type=$(detect_shell)
case "$shell_type" in
git-bash)
# Convert Windows path to Unix style
echo "$path" | sed 's|\\|/|g' | sed 's|^\([A-Z]\):|/\L\1|'
;;
*)
echo "$path"
;;
esac
}
# Usage
shell_type=$(detect_shell)
echo "Running in: $shell_type"
| 变量 | PowerShell | Git Bash | 用途 |
|---|---|---|---|
| 用户名 | $env:USERNAME | $USER | 当前用户 |
| 主目录 | $env:USERPROFILE | $HOME | 用户主目录 |
| 临时目录 | $env:TEMP | /tmp | 临时文件 |
| 路径列表 | $env:Path(; 分隔) | $PATH(: 分隔) | 可执行文件路径 |
| Shell 检测 | $env:PSModulePath | $MSYSTEM | Shell 标识符 |
PowerShell 访问环境变量:
$env:PATH # Current PATH
$env:PSModulePath # PowerShell module paths
$env:MSYSTEM # Would be empty in PowerShell
[Environment]::GetEnvironmentVariable("PATH", "Machine") # System PATH
Git Bash 访问环境变量:
echo $PATH # Current PATH
echo $MSYSTEM # Git Bash: MINGW64, MINGW32, or MSYS
echo $PSModulePath # Would be empty in pure Bash
PowerShell:
# Find files modified in last 7 days
Get-ChildItem -Path "C:\Projects" -Recurse -File |
Where-Object { $_.LastWriteTime -gt (Get-Date).AddDays(-7) } |
Select-Object FullName, LastWriteTime
Git Bash:
# Same operation in Git Bash
find /c/Projects -type f -mtime -7 -exec ls -lh {} \;
PowerShell:
# Stop all Chrome processes
Get-Process chrome -ErrorAction SilentlyContinue | Stop-Process -Force
Git Bash:
# Same operation in Git Bash
ps aux | grep chrome | awk '{print $2}' | xargs kill -9 2>/dev/null
PowerShell:
# Extract unique email addresses from logs
Get-Content "logs.txt" |
Select-String -Pattern '\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b' |
ForEach-Object { $_.Matches.Value } |
Sort-Object -Unique
Git Bash:
# Same operation in Git Bash
grep -oE '\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b' logs.txt |
sort -u
问题: 命令在一个 Shell 中有效,但在另一个中无效
# PowerShell
Get-Process # Works
# Git Bash
Get-Process # Command not found
解决方案: 理解 PowerShell cmdlet 在 Bash 中不存在。使用原生命令或在 Git Bash 中安装 PowerShell Core (pwsh):
# Run PowerShell from Git Bash
pwsh -Command "Get-Process"
问题: 路径在不同 Shell 中无效
# Git Bash path
/c/Users/John/file.txt # Works in Bash
# PowerShell
Test-Path "/c/Users/John/file.txt" # May fail
解决方案: 使用 cygpath 进行转换或规范化路径:
# Convert to Windows format for PowerShell
win_path=$(cygpath -w "/c/Users/John/file.txt")
pwsh -Command "Test-Path '$win_path'"
问题: ls、cd、cat 行为不同
# PowerShell
ls # Actually runs Get-ChildItem
# Git Bash
ls # Runs native Unix ls command
解决方案: 在 PowerShell 脚本中使用完整的 cmdlet 名称:
# Instead of: ls
Get-ChildItem # Explicit cmdlet name
$PSScriptRoot 处理脚本相对路径Join-Path 或 [IO.Path]::Combine() 处理路径$IsWindows、$IsLinux、$IsMacOS 进行平台检测$MSYSTEM 以检测 Git Bashcygpath 进行路径转换MSYS_NO_PATHCONV=1 以禁用自动转换(如需要)/c/...)最后更新: 2025年10月
每周安装次数
75
仓库
GitHub 星标数
21
首次出现
2026年1月24日
安全审计
安装于
gemini-cli59
opencode56
claude-code55
codex52
github-copilot48
cursor48
Critical guidance for distinguishing between PowerShell and Git Bash/MSYS2 shells on Windows, with shell-specific path handling and compatibility notes.
When working on Windows, correctly identifying the shell environment is crucial for proper path handling and command execution.
PSModulePath (Most Reliable):
# PowerShell detection
if ($env:PSModulePath) {
Write-Host "Running in PowerShell"
# PSModulePath contains 3+ paths separated by semicolons
$env:PSModulePath -split ';'
}
# Check PowerShell version
$PSVersionTable.PSVersion
# Output: 7.5.4 (PowerShell 7) or 5.1.x (Windows PowerShell)
PowerShell-Specific Variables:
# These only exist in PowerShell
$PSVersionTable # Version info
$PSScriptRoot # Script directory
$PSCommandPath # Script full path
$IsWindows # Platform detection (PS 7+)
$IsLinux # Platform detection (PS 7+)
$IsMacOS # Platform detection (PS 7+)
function Get-ShellType {
if ($PSVersionTable) {
return "PowerShell $($PSVersionTable.PSVersion)"
}
elseif ($env:PSModulePath -and ($env:PSModulePath -split ';').Count -ge 3) {
return "PowerShell (detected via PSModulePath)"
}
else {
return "Not PowerShell"
}
}
Get-ShellType
MSYSTEM Environment Variable (Most Reliable):
# Bash detection in Git Bash/MSYS2
if [ -n "$MSYSTEM" ]; then
echo "Running in Git Bash/MSYS2: $MSYSTEM"
fi
# MSYSTEM values:
# MINGW64 - Native Windows 64-bit environment
# MINGW32 - Native Windows 32-bit environment
# MSYS - POSIX-compliant build environment
Secondary Detection Methods:
# Using OSTYPE (Bash-specific)
case "$OSTYPE" in
msys*) echo "MSYS/Git Bash" ;;
cygwin*) echo "Cygwin" ;;
linux*) echo "Linux" ;;
darwin*) echo "macOS" ;;
esac
# Using uname (Most portable)
case "$(uname -s)" in
MINGW64*) echo "Git Bash 64-bit" ;;
MINGW32*) echo "Git Bash 32-bit" ;;
MSYS*) echo "MSYS" ;;
CYGWIN*) echo "Cygwin" ;;
Linux*) echo "Linux" ;;
Darwin*) echo "macOS" ;;
esac
| Aspect | PowerShell | Git Bash/MSYS2 |
|---|---|---|
| Environment Variable | $env:VARIABLE | $VARIABLE |
| Path Separator | ; (semicolon) | : (colon) |
| Path Style | C:\Windows\System32 | /c/Windows/System32 |
PowerShell Path Handling:
# Native Windows paths work directly
$path = "C:\Users\John\Documents"
Test-Path $path # True
# Forward slashes also work in PowerShell 7+
$path = "C:/Users/John/Documents"
Test-Path $path # True
# Use Join-Path for cross-platform compatibility
$configPath = Join-Path -Path $PSScriptRoot -ChildPath "config.json"
# Use [System.IO.Path] for advanced scenarios
$fullPath = [System.IO.Path]::Combine($home, "documents", "file.txt")
Git Bash Path Handling:
# Git Bash uses Unix-style paths
path="/c/Users/John/Documents"
test -d "$path" && echo "Directory exists"
# Automatic path conversion (CAUTION)
# Git Bash converts Unix-style paths to Windows-style
# /c/Users → C:\Users (automatic)
# Arguments starting with / may be converted unexpectedly
# Use cygpath for manual conversion
cygpath -u "C:\path" # → /c/path (Unix format)
cygpath -w "/c/path" # → C:\path (Windows format)
cygpath -m "/c/path" # → C:/path (Mixed format)
Git Bash/MSYS2 automatically converts paths in certain scenarios, which can cause issues:
# Leading forward slash triggers conversion
command /foo # Converts to C:\msys64\foo
# Path lists with colons
export PATH=/foo:/bar # Converts to C:\msys64\foo;C:\msys64\bar
# Arguments after dashes
command --path=/foo # Converts to --path=C:\msys64\foo
# Arguments with equals sign (variable assignments)
VAR=/foo command # NOT converted
# Drive specifiers
command C:/path # NOT converted
# Arguments with semicolons (already Windows format)
command "C:\foo;D:\bar" # NOT converted
# Double slashes (Windows switches)
command //e //s # NOT converted
# Disable ALL conversion (Git Bash)
export MSYS_NO_PATHCONV=1
command /foo # Stays as /foo
# Exclude specific patterns (MSYS2)
export MSYS2_ARG_CONV_EXCL="*" # Exclude everything
export MSYS2_ARG_CONV_EXCL="--dir=;/test" # Specific prefixes
Example PowerShell Scenario:
# Azure VM management with Az module
Connect-AzAccount
Get-AzVM -ResourceGroupName "Production" |
Where-Object {$_.PowerState -eq "VM running"} |
Stop-AzVM -Force
Example Git Bash Scenario:
# Git workflow with Unix tools
git log --oneline | grep -i "feature" | awk '{print $1}' |
xargs git show --stat
# Detect if running in PowerShell or Git Bash context
function Test-PowerShellContext {
return ($null -ne $PSVersionTable)
}
# Adapt path handling based on context
function Get-CrossPlatformPath {
param([string]$Path)
if (Test-PowerShellContext) {
# PowerShell: Use Join-Path
return (Resolve-Path $Path -ErrorAction SilentlyContinue).Path
}
else {
# Non-PowerShell context
Write-Warning "Not running in PowerShell. Path operations may differ."
return $Path
}
}
# Detect shell environment
detect_shell() {
if [ -n "$MSYSTEM" ]; then
echo "git-bash"
elif [ -n "$PSModulePath" ]; then
echo "powershell"
elif [ -n "$WSL_DISTRO_NAME" ]; then
echo "wsl"
else
echo "unix"
fi
}
# Adapt path handling
convert_path() {
local path="$1"
local shell_type=$(detect_shell)
case "$shell_type" in
git-bash)
# Convert Windows path to Unix style
echo "$path" | sed 's|\\|/|g' | sed 's|^\([A-Z]\):|/\L\1|'
;;
*)
echo "$path"
;;
esac
}
# Usage
shell_type=$(detect_shell)
echo "Running in: $shell_type"
| Variable | PowerShell | Git Bash | Purpose |
|---|---|---|---|
| Username | $env:USERNAME | $USER | Current user |
| Home Directory | $env:USERPROFILE | $HOME | User home |
| Temp Directory | $env:TEMP | /tmp |
PowerShell accessing environment variables:
$env:PATH # Current PATH
$env:PSModulePath # PowerShell module paths
$env:MSYSTEM # Would be empty in PowerShell
[Environment]::GetEnvironmentVariable("PATH", "Machine") # System PATH
Git Bash accessing environment variables:
echo $PATH # Current PATH
echo $MSYSTEM # Git Bash: MINGW64, MINGW32, or MSYS
echo $PSModulePath # Would be empty in pure Bash
PowerShell:
# Find files modified in last 7 days
Get-ChildItem -Path "C:\Projects" -Recurse -File |
Where-Object { $_.LastWriteTime -gt (Get-Date).AddDays(-7) } |
Select-Object FullName, LastWriteTime
Git Bash:
# Same operation in Git Bash
find /c/Projects -type f -mtime -7 -exec ls -lh {} \;
PowerShell:
# Stop all Chrome processes
Get-Process chrome -ErrorAction SilentlyContinue | Stop-Process -Force
Git Bash:
# Same operation in Git Bash
ps aux | grep chrome | awk '{print $2}' | xargs kill -9 2>/dev/null
PowerShell:
# Extract unique email addresses from logs
Get-Content "logs.txt" |
Select-String -Pattern '\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b' |
ForEach-Object { $_.Matches.Value } |
Sort-Object -Unique
Git Bash:
# Same operation in Git Bash
grep -oE '\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b' logs.txt |
sort -u
Problem: Command works in one shell but not another
# PowerShell
Get-Process # Works
# Git Bash
Get-Process # Command not found
Solution: Understand that PowerShell cmdlets don't exist in Bash. Use native commands or install PowerShell Core (pwsh) in Git Bash:
# Run PowerShell from Git Bash
pwsh -Command "Get-Process"
Problem: Paths don't work across shells
# Git Bash path
/c/Users/John/file.txt # Works in Bash
# PowerShell
Test-Path "/c/Users/John/file.txt" # May fail
Solution: Use cygpath for conversion or normalize paths:
# Convert to Windows format for PowerShell
win_path=$(cygpath -w "/c/Users/John/file.txt")
pwsh -Command "Test-Path '$win_path'"
Problem: ls, cd, cat behave differently
# PowerShell
ls # Actually runs Get-ChildItem
# Git Bash
ls # Runs native Unix ls command
Solution: Use full cmdlet names in PowerShell scripts:
# Instead of: ls
Get-ChildItem # Explicit cmdlet name
$PSScriptRoot for script-relative pathsJoin-Path or [IO.Path]::Combine() for paths$IsWindows, $IsLinux, $IsMacOS for platform detection$MSYSTEM for Git Bash detectioncygpath for path conversion when neededMSYS_NO_PATHCONV=1 to disable auto-conversion if needed/c/...) within BashLast Updated: October 2025
Weekly Installs
75
Repository
GitHub Stars
21
First Seen
Jan 24, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
gemini-cli59
opencode56
claude-code55
codex52
github-copilot48
cursor48
React 组合模式指南:Vercel 组件架构最佳实践,提升代码可维护性
122,000 周安装
Ralplan 共识规划工具:AI 驱动的迭代规划与决策制定 | 自动化开发工作流
213 周安装
ln-724-artifact-cleaner:自动清理在线平台项目产物,移除平台依赖,准备生产部署
204 周安装
Scanpy 单细胞 RNA-seq 数据分析教程 | Python 生物信息学工具包
206 周安装
AlphaFold 数据库技能:AI预测蛋白质3D结构检索、下载与分析完整指南
207 周安装
scikit-bio:Python生物信息学分析库,处理序列、比对、系统发育与多样性分析
207 周安装
xstate状态管理适配器:连接json-render与XState Store的状态后端解决方案
206 周安装
$env:USERPROFILE |
$HOME |
| Temp Directory | $env:TEMP | /tmp |
| Command Format | Get-ChildItem | ls (native command) |
| Aliases | PowerShell cmdlet aliases | Unix command aliases |
| Temporary files |
| Path List | $env:Path (; sep) | $PATH (: sep) | Executable paths |
| Shell Detection | $env:PSModulePath | $MSYSTEM | Shell identifier |