PowerShell: An Introduction for Linux Afficionados
Many of us cut our teeth on the elegant simplicity of the Linux command line, with its dazzling zero-based array of infinitely chainable commands. Then, with a dull thud you found yourself dumped rudely into the Windows environment, where things on the command line weren’t quite so peachy, to put it mildly. In fact, working in the old Windows command line was almost as fun as working in the trash compactor of the Death Star. Fortunately, with the advent of PowerShell, the dystopian landscape of the Windows console started to put forth a few shoots and sprigs of greenery. In this post I hope to show you some of our favorite Linux commands translated to their equivalent PowerShell cmdlets.
Fundamental Differences
PowerShell brings some interesting cards to the table, which differentiate it from the *Nix shellscape.
Objects, objects everywhere
In Linux, just about everything on the command line is text. A core principle of PowerShell is that just about everything is an object, and an object in the .NET environment to boot. This has some interesting implications. For one thing, it means that you’re not always seeing all of the available information on screen when you run a command in PowerShell. Many times it is possible to access additional properties of the object. I like to think of the default text that is output from a PowerShell command as coming from the .NET object’s ToString() method. Just as ToString() often doesn’t reveal all of the goodies within an object, the default output of a PowerShell command doesn’t always reveal the hidden pearls beneath that texty surface.
Consistent naming convention
Another big difference, which many view as a plus in its favor, is that PowerShell employs a consistent and expressive naming scheme. Once you start getting the hang of it, it can be easy to guess the names of other likely commands. The verbosity is annoying at first, but tab autocomplete and a number of built-in aliases speed things up a lot. Not only are command names more consistent, but the pattern for passing arguments is quite coherent as well. The *Nix’es, being the result of decades of eclectic contributions from the far reaches of the galaxy, aren’t as consistent in their naming and usage conventions. With arcane command names like awk, sed, grep, cat, cron, etc, the *Nix’es are certainly more fun and geeky than PowerShell, but the learning curve is a little steeper.
Making the transition
So if you’re a battle-hardened Linux guru and you’re using Windows, your first inclination may be to just install Gow and then get down to business. But you would be losing out on some of the benefits of PowerShell. First among them: PowerShell was made for Windows; Linux commands were not. :) So I recommend that you make the plunge and learn the equivalent PowerShell cmdlets for our beloved Linux commands.
Training wheels
As you’re learning, you might consider adding aliases for your Linux commands which just output hints to help you recall the equivalent PowerShell command. For example, open your PowerShell profile script (find out where it’s located with PowerShell’s $PROFILE variable) and add something like the following:
function grep { echo "The PS version of grep is Select-String, or sls" }
function cat { echo "The PS version of cat is Get-Content, or gc" }
Linux commands, translated to PowerShell cmdlets
cat
Linux:
cat myfile.txt
PowerShell
Get-Content myfile.txt
gc myfile.txt
grep
Linux:
git config --list | grep "auto"
grep searchstring file.txt
PowerShell
git config -- list | sls "auto"
Select-String searchstring file.txt
sls
stands for Select-String.more | less
Although the eponymous commands exist in PowerShell, avoid using less
and more
when chaining long running commands because they don’t start displaying anything until the previous command finishes processing everything. Instead, favor Out-Host
, shown here.
Linux:
ls -r | less
PowerShell
ls -r | out-host -Paging
ps
Linux:
ps aux
PowerShell
Get-Process
ps
and gps
so you will still feel at home here.ls
Linux:
ls .
PowerShell
ls .
ls
in PowerShell is an alias for Get-ChildItem
.As discussed earlier, since PS commands generally return objects rather than text, many of those objects’ properties are not printed to the screen when you execute the command. For example, to grab the FullName property of the returned objects:
ls | Select-Object fullname
kill
Linux:
kill explorer.exe
PowerShell
ps explorer | StopProcess
head|tail
Linux:
head -n10 file.txt
tail -n10 file.txt
PowerShell
gc file.txt | Select -first 10
gc file.txt | Select -last 10
wc
Linux:
Counting lines:
wc -l file.txt
PowerShell
gc file.txt | Measure-Object -Line
touch
Linux:
touch newFile.txt
PowerShell
New-Item -type file newFile.txt
rm
Linux:
rm oldFile.txt
PowerShell
Remove-Item oldFile.txt
rm
after all.)Get-Alias -Definition Remove-Item
sed
Of course sed
is huge, and this little example doesn’t do it justice. But hopefully it gets you started.
Linux:
cat file.txt | sed 's/example/WAZZUP/'
PowerShell
gc file.txt | %{ $_ -replace 'example', 'WAZZUP' }
Get-Content file.txt | ForEach-Object{ $_ -replace 'example', 'WAZZUP' }
This is an example in which I find the PowerShell version to be much harder to understand at first if you’re using the shorthand version. And since nobody wants to type ForEach-Object and the like, it’s the shorthand versions of PS cmdlets that you’ll typically find in the wild.
The longhand version demonstrates that the %{ } construct is shorthand for PowerShell’s ForEach-Object{ }
function.
The $_
refers to the current object in the pipeline, rather like Perl’s default variable of the same name $_
, or the input parameter in a lambda expression (x => x), or even as the this
variable in a class.
find
Linux:
find . -name "banana*"
PowerShell
ls -r banana*
Get-ChildItem -Filter banana* -recurse
The two PS examples are identical. The second example is just longhand for the first.
man
Linux:
man someCommand
PowerShell
Get-Help someCommand
help someCommand
help someCommand -examples
Additional PowerShell Tricks
Open an explorer window in the current directory
start .
Display all of the command aliases
Get-Alias
Get-Alias -Name ls
Get-Alias -Definition Get-ChildItem
View the implementation of a PowerShell function
gc function:/myFunction
Check which version of PowerShell you’re running
$PSVersionTable.PSVersion
So there you have it. Hopefully this little Linux->PowerShell translation primer will get you up and running in the world of PS. I’ll try to update this post with more commands in the future. And feel free to post your own Linux->PS goodies in the comments. Remember, don’t wait, automate. =)