PowerShell: An Introduction for Linux Afficionados

6 minute read Published:

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 Cygwin or 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
Note that Get-Process is aliased to both ps and gps so you will still feel at home here.

ls

Linux:

ls .

PowerShell

ls .
Well that was easy. Actually 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
Remove-Item is heavily aliased. Run the following command to see all of the possibilities. (You may find yourself using 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' }
Or, the more verbose longhand version:
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
Getting the PowerShell version

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. =)