When PowerShell was first released, the goal was to bring powerful scripting tools to Windows, which typically had GUI-based administration at the time. Since then, PowerShell has grown to become one of the most popular scripting languages.
One of the biggest contributors to this rise in popularity is that the PowerShell team at Microsoft made it open-source in 2016, introducing PowerShell Core for PowerShell version 6. However, that caused some unexpected issues, like having to support compatibility between version 5.1 (Windows PowerShell) and version 6.2 (PowerShell Core), or having the same cmdlets doing slightly different things on different versions of .NET.
To settle that, the PowerShell team announced they were retiring PowerShell 5.1 and that the next version after 6.2 would be PowerShell 7, which would aim to replace Windows PowerShell on Windows Operating systems without sacrificing any compatibility when running on Mac or Linux.
PowerShell 7 went GA in March of last year, and while the cmdlets themselves run on any operating system, there are still some best practices to follow to make sure your PowerShell scripts run smoothly no matter where they are running.
Use Lowercase Directory Names
In the Windows Operating system, the \ or backslash character is used to note nested directories in a file system, while in Linux and macOS, the / or forward-slash character does it instead and the backslash is used as an escape character. (If you ever have trouble keeping these two straight, just imagine it tipping over. Backslash falls back, forward slash falls forward)
This can make for some challenges when scripting in most other languages, but PowerShell 7 will translate either into a directory object and doesn’t really care about the characters used to split the path. One area where you can get into trouble, however, is that Linux and macOS file systems care about capitalization, and will treat directory names in different cases as different directories.
The best practice here is to keep directory names in lowercase, no matter what path you use. If you need to, you can pass in the path as a string and call the ToLower() method on it in your code, but this will only work if the directory name is already in lower case.
Don’t Use Aliasing
Aliasing can be a great way to shorten the amount of typing you have to do when running PowerShell from a console. It’s much easier to type ls or cgi than Get-ChildItem even with tab completion. That being said, it’s rarely a good idea to use aliases in scripts because it makes the script dependent on having that alias set wherever it runs.
That’s especially true for Linux and macOS systems. On those platforms, instead of using an alias to run another PowerShell command, it runs the native command, meaning that the return object is going to be very different, and that will throw off the rest of the script.
ls and Get-ChildItem running on Windows 10 vs Ubuntu Linux.
Some commands like ls might not change too much, but with others like the date command, PowerShell returns a completely different object from the native Linux command, which will throw off anything that is depending on the output later on in the code. Even if you just need the string value in a PowerShell script, use PowerShell to get it.
date returns a DateTime object on Windows and a String object on Linux.
Use a Switch Statement to Determine Operating System
Sometimes, you have a dependency that you can’t script around, no matter what kinds of tricks you use. In those cases, PowerShell 7 has a few reserved flags that will return true or false depending on what operating system you are running from. For example, $IsMacOS will return True on macOS and False on any other operating system, and $IsLinux will return True no matter which Linux distribution you are on.
There is also an $IsWindows flag, but with one big caveat: It only returns True when running PowerShell Core or PowerShell 7 on Windows. It was never ported back to Windows PowerShell, so it will just throw an error when running there.
Tyler Leonhardt from the PowerShell team at Microsoft came up with a great workaround for determining which OS you are on when running cross-platform, which is the switch statement he describes here.
Now you should have an idea of a few ways to write your PowerShell 7 scripts and modules so that they can run a little more smoothly cross-platform. Try them out in your scripts today!