PowerShell for Linux users
Most common operations
Like most people, there are some things I just cannot live without. Among them are some shell commands found in Linux like grep
or tail
.
A few years I found myself using Windows on a daily basis and, as you would expect, my favourite commands were nowhere to be found. In theory, I could just install GitBash and call it a day, but that is not always an option. On the other hand, PowerShell is always available, so learning a little bit about it seemed like a good idea.
If come from a Linux background and you found yourself in a spot, where PowerShell is the only tool available, this article might be just for you.
Navigating directories
One of the first things one learns when going to the shell of any operating system is how to navigate the directory tree. As such this is a good place to start learning PowerShell.
Finding the current location (pwd)
In Linux, to check the current location, pwd
is a very obvious choice. In PowerShell the same can be accomplished using Get-Location
. The output will look similar to this:
PS> Get-LocationPath
----
C:\Users\rszul
You might wonder why on Earth anyone would need more than one line to represent the current location. The reason for this is that we see a textual representation of a PathInfo
object. Yeah, PowerShell is object-oriented.
Changing directories (cd)
The simplest way to change the current location is to use the Set-Location
cmdlet. The syntax is as easy as you would expect — just provide the desired path, either absolute or relative to the current directory.
PS> Set-Location C:\
PS> Get-LocationPath
----
C:\
Changing directories like a pro (pushd & popd)
While no one will deny the usefulness of cd
and its PowerShell counterpart, there is another technique worth mentioning. Users of pushd
and popd
will be delighted to learn that there are two corresponding cmdlets.
Push-Location
and Pop-Location
work just like you’d expect, with the added bonus, that they support named stacks. What does this mean? Well, when using those cmdlets without any parameters, they behave like you’d expect. Push-Location
saves the current directory to a stack and changes it to whatever you typed in. Pop-Location
does the exact opposite: it changes your current directory to whatever is on the top of your saved stack and removes that entry. Take a look at the example below. Also take note that you cane use Get-Location
to display your whole stack!
PS> Get-LocationPath
----
C:\PS> Push-Location C:\Users\rszul
PS> Get-LocationPath
----
C:\Users\rszulPS> Get-Location -StackPath
----
C:\PS> Pop-Location
PS> Get-LocationPath
----
C:\
Just now we operated on a default stack, that doesn’t have na name. But if you’re a maestro at multitasking, you might want to keep things clean by namespacing your directory traversals. Just take a look at the following example and see for yourself.
PS> Get-LocationPath
----
C:\PS> Push-Location -StackName first C:\Users\rszul\
PS> Push-Location -StackName first C:\Users\rszul\Documents\
PS> Get-Location -StackName firstPath
----
C:\Users\rszul
C:\PS> Push-Location -StackName second C:\Windows\
PS> Push-Location -StackName second C:\Windows\System32\
PS> Get-Location -StackName secondPath
----
C:\Windows
C:\Users\rszul\Documents
Viewing files
In a previous article I showcased some use cases for commonly used commands in Linux, three of which, namely cat
, head
and tail
served a very similar purpose — to display a part of a like. Would you be surprised if I told you that their basic functionality a is packed into one cmdlet?
Displaying file contents (cat)
Get — Contents
is, as the name suggests used to display the contents of a file. So there is your cat
replacement. Unfortunately, it is a simple cmdlet and lacks the ability to change how whitespaces are displayed.
PS> Get-Content .\file.txt
1
2
3
4
Get head and tail (head & tail)
It turns out that you can also use Get-Contents
as a direct replacement for head
and tail
. It comes with two options: Head
and Tail
both of which display a given number of lines.
PS> Get-Content -Head 2 .\file.txt
1
2
PS> Get-Content -Tail 2 .\file.txt
3
4
Once again, packing the functionality of three Linux commands into one cmdlet comes at a price. There is no support for more advanced scenarios.
Pagination (more, less & more)
At some point you will encounter a file that is simply too large to fit on your screen. At those times you could try your luck and just scroll up in the terminal until you, eventually, find the first line. A more sane approach would be to paginate the output.
In Linux, the battle seems to rage between more
, less
and most
as the best pagination tool. For some reason every OS seems to have more than one way to accomplish this task. There are two main ways to do this in a PowerShell terminal: more
and Out-Host -Paging
. Their usage is also very similar and involves the usage of pipes. Sample commands are:
PS> Get-Content .\file.txt | more
(...)PS> Get-Content .\file.txt | Out-Host –Paging
(...)
Obviously it’s hard to demonstrate pagination in an article, so I’ll leave this as an exercise to the reader. You will notice, however, that both options lack many advanced features such as backwards scrolling or text searching.
Finding patterns in text (grep)
Now we know how to display file contents, but is there an easy way to substitute grep
? Well, there is. Select-String
is your friend when it comes to finding specific patterns. The most basic usage would be to find a string inside of a file. Here’s a simple example, where we try to find any occurrence of the character “1”.
PS> Get-Content .\file2.txt
1
3
11
12PS> Get-Content .\file2.txt | Select-String -SimpleMatch 11
11
12
It’s also possible to use regex. Here we try to find every line that contains alt least one “1” and nothing else.
PS> Get-Content .\file2.txt | Select-String -Pattern '^1+$'1
11
Select-String
is also able to emulate the behaviour of -A
and -B
options that we know from grep
. They are bundled together in one parameter, which will change its behaviour based on the supplied value. So to view N lines before and after a match, you’d do something like this: -Context N
. It is also possible to change the number of displayed lines before and after the match. Assuming you want to view N lines before and M lines after the match, the parameter would take this form: -Context N,M
. Let’s see this in action. Notice how the matched line is marked with a cute arrow. Love it.
PS> Get-Content .\file2.txt | Select-String -Pattern '3' -Context 1 1
> 3
11PS> Get-Content .\file2.txt | Select-String -Pattern '3' -Context 1,2 1
> 3
11
12
Listing directories (ls)
The best way to view the contents of any directory is to use the Get-ChildItem
cmdlet. The output is also very similar to what we’re used to.
> Get-ChildItemDirectory: C:\Users\rszul\PicturesMode LastWriteTime Length Name
---- ------------- ------ ----
d-r--- 22.10.2021 19:47 Camera Roll
d-r--- 22.10.2021 19:47 Saved Pictures
-a---- 03.12.2021 12:12 38769 mata.png
-a---- 08.02.2022 21:25 26761 stats.png
It is also possible to display hidden files and directories by providing the -Hidden
parameter. Doing so will display only hidden items. If you want a direct ls -la
replacement, you need to execute this cmdlet with -Force
parameter, which probably wouldn’t be your first guess.
Get-ChildItem
also provides us with a nice way to filter desired output. When using Linux you probably did something like this nume,rous times: ls -la | grep myfile
. With Get-ChildItem
it is possible to do something alike using filter patterns. Here’s an example, where we try to find all PNG files.
PS> Get-ChildItem -Filter '*png'Directory: C:\Users\rszul\PicturesMode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 03.12.2021 12:12 38769 mata.png
-a---- 08.02.2022 21:25 26761 stats.png
Moving and copying files (cp, mv)
Once we learned that “stuff” in our folders is referenced to as “item”, operating on files becomes quite easy. With this it becomes easy to understand that moving a file will be the same as moving an item, hence Move-Item
is what we need. Similarly, to copy an item use Copy-Item
. Of course the meaning of “item” depends on the context and it’s not always a file. Sometimes it can be a registry key.
The usage is very similar to what we know from Linux. Note the presence of $HOME
variable, which is the users home folder.
PS> Copy-Item .\mata.png $HOME
PS> Move-Item .\stats.png $HOME
Of course both cmdlets have support for both -Force
and -Recurse
parameters, which work as expected.
Getting help (man)
In Linux there are two main ways of getting help when stuck with a command. One is the built-in help of said command, usually accessed via -h
or --help
. The other one comes in the form of man pages. Granted, PowerShell does not lag behind in this regard.
If you ever need to read up on a command Get-Help is your friend. Taking Copy-Item as an example:
PS> Get-Help Copy-ItemNAME
Copy-ItemSYNOPSIS
Copies an item from one location to another.(...)
This displays some basic information about the cmdlet, redacted for readability. If you need even more information, there are parameters for that: -Detailed
and -Full
. Try it out! But by far my favourite part is the option to display the manual in a browser. Executing Get-Help Copy-Item -Online
will open the official Microsoft documentation in your favourite web browser!
Conclusion
In this article we looked at some commonly used Linux command and their counterparts in PowerShell. You will notice the astounding lack of a command to edit files. This is because I refuse to write about notepad.exe
, which is the only pre-installed text editor (if I’m wrong, please let me know).
Pipes and output redirection deserve their own article, so I tried to avoid them as much as possible.
Did I miss your favourite command? Let me know!