Using ICACLS to set file permission to 'read-only'

15,621

Permissions in Unix and Windows work in different ways. In Windows you have inheritance by default and permissions are more granular because you have ACEs (permissions per identity), not just owner/group/other. Permissions for the owner is only given on creation. If you change owner later, you need to manually update ACEs before the owner can modify the file.

Because of this, you need to know who you want to give permissions to. If you want to only give read permission to the user you are logged on with, you can use $env:username in PowerShell or %USERNAME% in cmd.

Examples using PowerShell:

$path = ".\test.txt"
#Reset to remove explict permissions
icacls.exe $path /reset
#Give current user explicit read-permission
icacls.exe $path /GRANT:R "$($env:USERNAME):(R)"
#Disable inheritance and remove inherited permissions
icacls.exe $path /inheritance:r

If you want set it equal to chmod 400, you can check who's the owner and assign permissions to that account. Be aware that this can also be a group like Administrators:

$path = ".\test.txt"
icacls.exe $path /reset
icacls.exe $path /GRANT:R "$((Get-Acl -Path $path).Owner):(R)"
icacls.exe $path /inheritance:r

Or you can use the built-in cmdlets in PowerShell:

$path = ".\test.txt"

#Get current ACL to file/folder
$acl = Get-Acl $path

#Disable inheritance and remove inherited permissions
$acl.SetAccessRuleProtection($true,$false)

#Remove all explict ACEs
$acl.Access | ForEach-Object { $acl.RemoveAccessRule($_) }

#Create ACE for owner with read-access. You can replace $acl.Owner with $env:UserName to give permission to current user
$ace = New-Object System.Security.AccessControl.FileSystemAccessRule -ArgumentList $acl.Owner, "Read", "Allow"
$acl.AddAccessRule($ace)

#Save ACL to file/folder
Set-Acl -Path $path -AclObject $acl
Share:
15,621
Kyle Vassella
Author by

Kyle Vassella

Started from the bottom, now we've got an expandable user card.

Updated on June 14, 2022

Comments

  • Kyle Vassella
    Kyle Vassella almost 2 years

    I'm having a heck of a time transferring from the simple, intuitive chmod 400 to trying to do the same thing in Windows Command Prompt using ICACLS. Compared to the sleek, octal representation of UNIX/LINUX's chmod, ICACLS seems a complex nightmare.

    I have a SSH .pem key which I'm trying to make read-only. I want to replace the old permissions which are currently on it with this new, read-only permission. The closest I've come to finding an answer is the following:

    ICACLS "D:\Folder A\Another Folder\File Name Here.ext" /GRANT:R "DOMAIN\USERNAME":R
    (found here: https://www.experts-exchange.com/questions/27624477/What-command-can-give-user-read-only-permission.html)

    I believe the :R at the very end allows me to replace the current permissions, which is what I want. But I don't know what to put for the "DOMAIN\USERNAME"segment. Any advice?

  • Kyle Vassella
    Kyle Vassella about 7 years
    I don't think so - I was reading that you're really supposed to use ICACLS to change the file permissions and not attrib - plus I don't think adding the read attribute will remove the write and execute permissions already on the file. Thank you for trying though!
  • Joe Berg
    Joe Berg over 4 years
    Thank you. This is still relevant and saved me after quite a bit of searching
  • Dennis
    Dennis almost 4 years
    great answer, thanks. Typo in the second example where you are not modifying the owner. Line 3 should be icacls.exe $path /GRANT:R "$((Get-Acl -Path $path).Owner):(R)"
  • Paul Pritchard
    Paul Pritchard almost 2 years
    Worked a treat for me, just typing each command in at the PowerShell prompt. Thank you @frode-f