In this article

What's New in PowerShell Core 6.0

In this article

PowerShell Core 6.0 is a new edition of PowerShell that is cross-platform (Windows, macOS, and Linux), open-source, and built for heterogeneous environments and the hybrid cloud.

Moved from .NET Framework to .NET Core

PowerShell Core uses .NET Core 2.0 as its runtime.
.NET Core 2.0 enables PowerShell Core to work on multiple platforms (Windows, macOS, and Linux).
PowerShell Core also exposes the API set offered by .NET Core 2.0 to be used in PowerShell cmdlets and scripts.

Windows PowerShell used the .NET Framework runtime to host the PowerShell engine.
This means that Windows PowerShell exposes the API set offered by .NET Framework.

The APIs shared between .NET Core and .NET Framework are defined as part of .NET Standard.

Our community has also contributed packages for the following platforms,
but they are not officially supported:

Arch Linux

Kali Linux

AppImage (works on multiple Linux platforms)

We also have experimental (unsupported) releases for the following platforms:

Windows on ARM32/ARM64

Raspbian (Stretch)

A number of changes were made to in PowerShell Core 6.0 to make it work better on non-Windows systems.
Some of these are breaking changes, which also affect Windows.
Others are only present or applicable in non-Windows installations of PowerShell Core.

Added support for native command globbing on Unix platforms.

The more functionality respects the Linux $PAGER and defaults to less.
This means you can now use wildcards with native binaries/commands (for example, ls *.txt). (#3463)

Logging

Filesystem

A number of changes have been made on macOS and Linux to support filename characters not traditionally supported on Windows:

Paths given to cmdlets are now slash-agnostic (both / and \ work as directory separator)

XDG Base Directory Specification is now respected and used by default:

The Linux/macOS profile path is located at ~/.config/powershell/profile.ps1

The history save path is located at ~/.local/share/powershell/PSReadline/ConsoleHost_history.txt

The user module path is located at ~/.local/share/powershell/Modules

Support for file and folder names containing the colon character on Unix. (#4959)

Support for script names or full paths that have commas. (#4136) (Thanks to @TimCurwick!)

Detect when -LiteralPath is used to suppress wildcard expansion for navigation cmdlets. (#5038)

Updated Get-ChildItem to work more like the *nix ls -R and the Windows DIR /S native commands.
Get-ChildItem now returns the symbolic links encountered during a recursive search and does not search the directories that those links target. (#3780)

Case sensitivity

Linux and macOS tend to be case-sensitive while Windows is case-insensitive while preserving case.
In general, PowerShell is case insensitive.

For example, environment variables are case-sensitive on macOS and Linux,
so the casing of the PSModulePath environment variable has been standardized. (#3255)
Import-Module is case insensitive when it's using a file path to determine the module's name. (#5097)

Support for side-by-side installations

PowerShell Core is installed, configured, and executed separately from Windows PowerShell.
PowerShell Core has a "portable" ZIP package.
Using the ZIP package, you can install any number of versions anywhere on disk, including local to an application that takes PowerShell as a dependency.
Side-by-side installation makes it easier to test new versions of PowerShell and migrating existing scripts over time.
Side-by-side also enables backwards compatibility as scripts can be pinned to specific versions that they require.

Note

By default, the MSI-based installer on Windows does an in-place update install.

Renamed powershell(.exe) to pwsh(.exe)

The binary name for PowerShell Core has been changed from powershell(.exe) to pwsh(.exe).
This change provides a deterministic way for users to run PowerShell Core on machines to support side-by-side Windows PowerShell and PowerShell Core installations.
pwsh is also much shorter and easier to type.

Additional changes to pwsh(.exe) from powershell.exe:

Changed the first positional parameter from -Command to -File.
This change fixes the usage of #! (aka as a shebang) in PowerShell scripts that are being executed from non-PowerShell shells on non-Windows platforms.
It also means that you can run commands like pwsh foo.ps1 or pwsh fooScript without specifying -File.
However, this change requires that you explicitly specify -c or -Command when trying to run commands like pwsh.exe -Command Get-Command. (#4019)

PowerShell Core accepts the -i (or -Interactive) switch to indicate an interactive shell. (#3558)
This allows PowerShell to be used as a default shell on Unix platforms.

Backwards compatibility with Windows PowerShell

The goal of PowerShell Core is to remain as compatible as possible with Windows PowerShell.
PowerShell Core uses .NET Standard 2.0 to provide binary compatibility with existing .NET assemblies.
Many PowerShell modules depend on these assemblies (often times DLLs), so .NET Standard allows them to continue working with .NET Core.
PowerShell Core also includes a heuristic to look in well-known folders--like where the Global Assembly Cache typically resides on disk--to find .NET Framework DLL dependencies.

You can learn more about .NET Standard on the .NET Blog, in this YouTube video, and via this FAQ on GitHub.

Best efforts have been made to ensure that the PowerShell language and "built-in" modules (like Microsoft.PowerShell.Management, Microsoft.PowerShell.Utility, etc.) work the same as they do in Windows PowerShell.
In many cases, with the help of the community, we've added new capabilities and bug fixes to those cmdlets.
In some cases, due to a missing dependency in underlying .NET layers, functionality was removed or is unavailable.

Most of the modules that ship as part of Windows (for example, DnsClient, Hyper-V, NetTCPIP, Storage, etc.) and other Microsoft products including Azure and Office have not been explicitly ported to .NET Core yet.
The PowerShell team is working with these product groups and teams to validate and port their existing modules to PowerShell Core.
With .NET Standard and CDXML, many of these traditional Windows PowerShell modules do seem to work in PowerShell Core,
but they have not been formally validated, and they are not formally supported.

By installing the WindowsPSModulePath module,
you can use Windows PowerShell modules by appending the Windows PowerShell PSModulePath to your PowerShell Core PSModulePath.

First, install the WindowsPSModulePath module from the PowerShell Gallery:

SSH-based PowerShell Remoting

The PowerShell Remoting Protocol (PSRP) now works with the Secure Shell (SSH) protocol in addition to the traditional WinRM-based PSRP.

This means that you can use cmdlets like Enter-PSSession and New-PSSession and authenticate using SSH.
All you have to do is register PowerShell as a subsystem with an OpenSSH-based SSH server,
and you can use your existing SSH-based authenticate mechanisms (like passwords or private keys) with the traditional PSSession semantics.

Default encoding is UTF-8 without a BOM except for New-ModuleManifest

In the past, Windows PowerShell cmdlets like Get-Content, Set-Content used different encodings, such as ASCII and UTF-16.
The variance in encoding defaults created problems when mixing cmdlets without specifying an encoding.

Non-Windows platforms traditionally use UTF-8 without a Byte Order Mark (BOM) as the default encoding for text files.
More Windows applications and tools are moving away from UTF-16 and towards BOM-less UTF-8 encoding.
PowerShell Core changes the default encoding to conform with the broader ecosystems.

This means that all built-in cmdlets that use the -Encoding parameter use the UTF8NoBOM value by default.
The following cmdlets are affected by this change:

Add-Content

Export-Clixml

Export-Csv

Export-PSSession

Format-Hex

Get-Content

Import-Csv

Out-File

Select-String

Send-MailMessage

Set-Content

These cmdlets have also been updated so that the -Encoding parameter universally accepts System.Text.Encoding.

The default value of $OutputEncoding has also been changed to UTF-8.

As a best practice, you should explicitly set encodings in scripts using the -Encoding parameter to produce deterministic behavior across platforms.

New-ModuleManifest cmdlet does not have Encoding parameter. The encoding of the module manifest (.psd1) file created with New-ModuleManifest cmdlet depends on environment: if it is PowerShell Core running on Linux then encoding is UTF-8 (no BOM); otherwise encoding is UTF-16 (with BOM). (#3940)

Support backgrounding of pipelines with ampersand (&) (#3360)

Putting & at the end of a pipeline causes the pipeline to be run as a PowerShell job.
When a pipeline is backgrounded, a job object is returned.
Once the pipeline is running as a job, all of the standard *-Job cmdlets can be used to manage the job.
Variables (ignoring process-specific variables) used in the pipeline are automatically copied to the job so Copy-Item $foo $bar & just works.
The job is also run in the current directory instead of the user's home directory.
For more information about PowerShell jobs, see about_Jobs.

Engine updates

PSEdition: This is set to Core on PowerShell Core and Desktop on Windows PowerShell

GitCommitId: This is the Git commit ID of the Git branch or tag where PowerShell was built.
On released builds, it will likely be the same as PSVersion.

OS: This is an OS version string returned by [System.Runtime.InteropServices.RuntimeInformation]::OSDescription

Platform: This is returned by [System.Environment]::OSVersion.Platform
It is set to Win32NT on Windows, Unix on macOS, and Unix on Linux.

Removed the BuildVersion property from $PSVersionTable.
This property was strongly tied to the Windows build version.
Instead, we recommend that you use GitCommitId to retrieve the exact build version of PowerShell Core. (#3877) (Thanks to @iSazonov!)

Remove ClrVersion property from $PSVersionTable.
This property is irrelevant for .NET Core, and was only preserved in .NET Core for specific legacy purposes that are inapplicable to PowerShell.

Added three new automatic variables to determine whether PowerShell is running in a given OS:
$IsWindows, $IsMacOs, and $IsLinux.

Add GitCommitId to PowerShell Core banner.
Now you don't have to run $PSVersionTable as soon as you start PowerShell to get the version! (#3916) (Thanks to @iSazonov!)

Add a JSON config file called powershell.config.json in $PSHome to store some settings required before startup time (e.g. ExecutionPolicy).

For Invoke-WebRequest, when the response includes a Link header we create a RelationLink property as a Dictionary representing the URLs and rel attributes and ensure the URLs are absolute to make it easier for the developer to use.

For Invoke-RestMethod, when the response includes a Link header we expose a -FollowRelLink switch to automatically follow nextrel links until they no longer exist or once we hit the optional -MaximumFollowRelLink parameter value.

Telemetry

If you want to opt-out of this telemetry, simply create POWERSHELL_TELEMETRY_OPTOUT environment variable with one of the following values: true, 1 or yes.
Creating the variable bypasses all telemetry even before the first run of PowerShell.
We also plan on exposing this telemetry data and the insights we glean from the telemetry in the community dashboard.
You can find out more about how we use this data in this blog post.

Feedback

We'd love to hear your thoughts. Choose the type you'd like to provide: