Last Update: Sep 04, 2024 | Published: Apr 10, 2020
With the introduction of PowerShell Core and now PowerShell 7, the cross-platform capabilities of PowerShell have also brought new challenges. System administrators used to working on Windows systems that now operate cross-platform need to be able to handle permissions in similar ways. With that in mind, how does PowerShell 7 handle Linux permissions?
In Windows, to view a set of files and folder permissions, you may run the Get-ChildItem
command to see the mode, much like ls -l
on Linux works, but this only tells you the directory and file attributes. To see the permission of a particular file or folder, the Get-ACL
command must be used.
PowerShell in Linux does not have that command, therefore there is no way to view the folder permissions using traditional PowerShell filesystem providers. For example, running Get-ChildItem
on Linux will show the following.
Compare this to ls -l
output and you can see how the permissions are missing. Ideally, to make working with permissions in Linux easier, we could add to the Get-ChildItem
output and show the permissions, owners, and groups.
The easiest method to retrieve the permissions is to pull the output from ls -l file.ext
and add that as a property to the existing Get-ChildItem
output. To start with, lets split the output of ls -l file.ext
and return just the permissions and full file name.
Get-ChildItem | ForEach-Object {
$_.FullName
((ls -l $_.FullName) -Split " ")[0]
}
Next, we want to add the owner and group permissions to our output. This is easy to do as all we need is additional values contained within the existing split string.
Get-ChildItem | ForEach-Object {
$string = ((ls -l $_.FullName) -Split " ")
$_.FullName
$String[0]
$String[2]
$String[3]
}
This is a great start, but obviously we need to clean this up a bit and make the output more readable and user friendly.
A very flexible method for creating one’s own parseable objects is to use the [PSCustomObject]
type. This allows one to create an object with any type of properties quickly and easily. For example, taking our above output and putting this in a custom object is easy as shown below.
Get-ChildItem | ForEach-Object {
$string = ((ls -l $_.FullName) -Split " ")
[PSCustomObject]@{
"FullName" = $_.FullName
"Permissions" = $String[0]
"Group" = $String[2]
"User" = $String[3]
}
}
As you can tell, this is much more akin to the output that one may expect to see. This allows for cmdlets such as Where-Object
or Select-Object
to be easily used to filter the results. Of course, there are many more properties that Get-ChildItem
has that are not exposed here because we are only returning some of the properties.
How do we take what we have learned above and translate that into better Linux permission support for Get-ChildItem
. The easiest way is to create a new wrapper function, that in this case, we will call Get-ChildLinuxItem
.
Function Get-ChildLinuxItem {
[CmdletBinding()]
Param(
[Parameter(Position = 0)][String]$Name
)
Process {
($Name ? ($Name | Get-ChildItem) : (Get-ChildItem)) | ForEach-Object {
$string = ((ls -l $_.FullName) -Split " ")
[PSCustomObject]@{
"FullName" = $_.FullName
"Permissions" = $String[0]
"Group" = $String[2]
"User" = $String[3]
}
}
}
}
As it currently stands this function doesn’t work on pipelined input and has a single parameter. Though we are not intending to replicate every aspect of Get-ChildItem
, the main goal here is to return most existing Get-ChildItem
properties.
The best way to add additional properties to an existing object is through the Add-Member
cmdlet. This lets us use the existing object properties and then merely add on the Permissions
, Group
, and User
properties. Just looking at the Process
block then, we change this up to use the following Add-Member
functionality.
($Name ? ($Name | Get-ChildItem) : (Get-ChildItem)) | ForEach-Object {
$object = $_
$string = ((ls -l $object.FullName) -Split " ")
$object | Add-Member -Name 'Permissions' -Value $String[0] -MemberType 'NoteProperty'
$object | Add-Member -Name 'Group' -Value $String[2] -MemberType 'NoteProperty'
$object | Add-Member -Name 'User' -Value $String[3] -MemberType 'NoteProperty'
$object
}
Running Get-ChildLinuxItem
we get the following:
Wait a minute, what happened to our new properties? Well because we are now returning the default Get-ChildItem
objects, they are subject to the default formatter rules and show properties accordingly. So how do we make the same appear but with our added properties? Select just the properties we want to show.
$object | Select-Object Permissions, Group, User, LastWriteTime, Name
To see this in the traditional table view, send the following output to Format-Table -AutoSize
.
At the end of all that, it seems that we have a roughly equivalent object and display to what ls -l
might give us. So what are the limitations, in our admittedly simple fuction?
Get-ChildItem
parametersSelect-Object
and Format-Table
Though there are more, these two are pretty large ones. To address the first, one may need to create a proxy function of Get-ChildItem
and add an additional parameter that does the work to add on the extra properties. Due to the complexity of creating a proxy function (though not unreasonable), we don’t cover that in this article. The second problem, regarding the output, could be resolved by creating a new default formatting file that outputs the new properties that don’t rely on a select or format cmdlet. This would generally go hand-in-hand with the proxy function as the System.IO.FileInfo
type (output by Get-ChildItem
) could be assumed to have those properties.
Though Linux permission PowerShell 7 support is not natively included, there are ways to utilize core functionality and extend the default cmdlets to output relevant information that can then be further used in scripts and other cmdlets.
Related Article: