In a modern Linux environment, it’s increasingly common to find both PowerShell (pwsh) and Bash installed on the same system. This provides a unique opportunity for system administrators and developers to leverage the strengths of both shells. You can use Bash for its powerful text-processing utilities and then pipe the results to PowerShell for its object-oriented data manipulation, or vice versa.
This guide will walk you through the techniques for calling Bash from PowerShell and PowerShell from Bash, enabling you to create powerful, cross-shell automation scripts.
Part 1: Calling Bash Commands from PowerShell
PowerShell on Linux is designed to work seamlessly with native Linux commands. This makes it easy to incorporate traditional shell tools into your PowerShell scripts.
Simple Commands
For simple commands, you can just type them as you would in Bash. PowerShell will recognize that it’s not a built-in cmdlet and execute it as a native command.
# These are native Linux commands, not PowerShell cmdlets
ls -l /etc
grep "error" /var/log/syslogImportant Note: The output from these commands is a stream of plain text strings, not PowerShell objects. You can, however, pipe this to other PowerShell cmdlets for further processing.
# Get a list of files from 'ls' and filter them with a PowerShell cmdlet
$files = ls /var/log
$files | Select-String "syslog"Complex Commands with bash -c
For more complex Bash syntax, such as loops, pipelines, or variable assignments, it’s best to explicitly invoke Bash using bash -c.
# Use single quotes to ensure the string is passed to Bash as-is
bash -c 'for i in {1..3}; do echo "File $i"; done'You can also pass PowerShell variables to your Bash command, but be careful with quoting.
$path = "/tmp"
# Use double quotes here to allow the PowerShell variable to be expanded
bash -c "ls -l $path"Part 2: Calling PowerShell from Bash
You can just as easily call PowerShell from a Bash script using the pwsh executable.
Running a Single Command with pwsh -c
The -c (or -Command) parameter allows you to execute a single line of PowerShell code from your Bash terminal.
# Get detailed process information using a PowerShell cmdlet
pwsh -c "Get-Process | Where-Object CPU -gt 100"Quoting is critical here. It’s often best to wrap your PowerShell command in single quotes to prevent the Bash shell from interpreting special characters like $.
Executing a .ps1 Script
To execute a PowerShell script file (.ps1) from Bash, use the -File parameter.
Example PowerShell script (/home/user/scripts/test.ps1):
Param([string]$Name)
Write-Host "Hello, $Name, from a PowerShell script!"Run it from Bash with parameters:
pwsh -File /home/user/scripts/test.ps1 -Name "LinuxUser"Capturing PowerShell Output in Bash
You can capture the text output from a PowerShell command into a Bash variable using command substitution ($()).
# Get the current date from PowerShell and store it in a Bash variable
CURRENT_DATE=$(pwsh -c "Get-Date -Format 'yyyy-MM-dd'")
echo "Today's date is: $CURRENT_DATE"The Challenges: Quoting and Data Types
When you mix shells, you need to be aware of two main challenges:
- Quoting: Bash and PowerShell have different rules for how they interpret single (
') and double (") quotes and special characters like$. When nesting one shell inside the other, it’s easy to make a mistake. Rule of thumb: Use single quotes to pass a command as a literal string. - Data Types: The biggest difference is that PowerShell works with objects, while Bash works with text. When you pass data from PowerShell to Bash, the rich object is converted into a plain text representation. When you pass data from Bash to PowerShell, it is received as an array of strings. Always be prepared to work with strings at the boundary between the two shells.
Best Practices for Cross-Shell Scripting
- Check Exit Codes: After running a native command in PowerShell, check the
$LASTEXITCODEautomatic variable to see if it succeeded. In Bash, check the$?variable after running apwshcommand. - Use
bash -cfor complex logic: Don’t try to replicate complex Bash scripts line-by-line in PowerShell. Just wrap the whole thing inbash -c '...'. - Use PowerShell for structured data: If you need to work with structured data like JSON or CSV, do it in PowerShell. Use
pwsh -cto call a PowerShell command that can parse the data and then return a simple string result to Bash.
Conclusion
PowerShell and Bash are not competitors on Linux; they are powerful collaborators. By understanding how to call one from the other, you can build incredibly flexible and powerful automation scripts that leverage the best features of both worlds.
- Use Bash for its strengths in text manipulation and its vast ecosystem of command-line tools.
- Use PowerShell for its strengths in working with structured data, its object-oriented pipeline, and its consistent scripting language across platforms.
By mastering cross-shell scripting, you can become a more effective and versatile system administrator in any environment.