How to Use the Icacls Command to Manage File Permissions


Icacls is a Windows command-line utility that IT admins can use to change access control lists on files and folders. One of the most common tasks that an IT Pro or system administrator performs is modifying permission on a file server. Using the icacls command is a very efficient way to do that, and we’ll explain how to use this command in this guide.

How to use the icacls command

Based on my own personal experience, modifying file permissions on Windows is usually done using File Explorer. For many IT folks, it’s very intuitive to open File Explorer, browse to the network location causing issues for some users’ access, and change their permissions from ‘Read’ to ‘Read/Modify’ or something similar. Nice and quick, fairly easy to use.

However, there are countless scenarios encompassing varying levels of scope where the GUI just isn’t as robust as we’d like. If we’re going to change permissions on 22 million files and folders, we want to do it right!

What is an access control list (ACL)?

In Windows and NTFS filesystems, each file object (file, folder) has an access control list. This list is made up of access control entries (ACE). The list contains all the users and/or other security container objects (groups, etc.) that have some level of permission to said file object.

What is an access control entry? One moment…

What is an access control entry (ACE)?

An access control entry (ACE) is an individual record or permission rule which controls the individual permission levels of a user/group on a file object. Let me list out the high-level basic permissions available for an ACL:

  • Full access (F)
  • Modify access (M) (includes ‘delete’)
  • Read and execute access (RX)
  • Read-only access (R)
  • Write-only access (W)

There are about a dozen or more ‘advanced’ permissions, but those are beyond the scope of this article.

File Explorer limitations

Now, if I was the program manager at Microsoft for File Explorer (NOT a job I particularly envy), these are the features I would add. And trust me, I’ve wanted them to add these for decades!

Let’s say you’re handling a file server migration from Server A to Server B. You’ve already copied the data to the destination (Server B). You have discovered that not all the permissions recursively look right.

So, you go to the root of your tree, get into the Security tab, and make a few changes to the access control list. You check the box to recursively modify all 22 million files and folders underneath the root. It starts making changes and then throws a few confirmation pop-ups to you about making changes to system files, read-only files, etc.

Now, here is my request – In the mini ‘wizard’ they could create, I want to specify to simply assume and click ‘Yes’ on all requests for confirmation. Then, the process would continue on any errors and then offer me a summary when it’s done, with a link to download the raw output of the file so I can go back and check on any errors or warnings that did pop up.

No, I don’t know if Microsoft will ever offer such a wonderful, robust, set-it-and-forget-it feature set as this. So, in the meantime, we go to the power of the command line and scripting. That is where the built-in icacls command comes in.

Understanding the icacls syntax

The icacls syntax is actually pretty straightforward and relatively easy to learn. Basically, you use the command, then add the file or folder you want to check or manipulate, and then the permission(s) you want to add/change/delete.

There are command-line switches, too, of course. We will cover all of this soon. Here is an example of what happens when you just run the following command and then a filename.

icacls Excellent.txt
Using icacls to view current permissions
Using icacls to view current permissions

It will output one ACE per line, so using the example above:

  • The built-in ‘SYSTEM’ account has Inherited (I) and Full (F) access permissions
  • The built-in Administrators group has the same permissions
  • The built-in Users group has Inherited (I), Read (R), and Execute (X) permissions.

Can you use icacls in PowerShell?

Well, as you can see from my example above and screenshot, you certainly can use PowerShell to use the icacls command. You only need to be aware of some environment variables that need to be referenced a little differently.

The equivalent PowerShell cmdlets to view and manage ACLs on file objects are Get-Acl and Set-Acl. It sounds like a future post idea! 😉

Using icacls to set up permissions for a file or folder

Because the icacls command is built-in on Windows, you’re free to start using the command as soon as you understand the basics here. You can also just type ‘icacls’ by itself on the command line to view the available Help information. You can also browse similar Microsoft documentation for the icacls command on this page.

How to display the current ACL for an object

Alright, I think that’s enough exposition… let’s get started on using the command. To display the current ACL for a file or directory, simply use the following commands:

icacls file or directory
icacls Download
Using icacls to view permissions on a folder
Using icacls to view permissions on a folder

Here, ‘Download’ is a folder with files and subfolders. As you will note, the output is a little different for directory objects. You’ll see (OI) and (CI) because these are special container inheritance-level permissions that only apply to directories.

For the built-in Administrators group, you see it has full rights and inherited permissions. The ‘(OI)’ shows that the other objects in this directory will inherit this ACE. The ‘(CI)’ shows that other folders in this directory will again inherit this ACE. (This directory doesn’t happen to have any, but if it did, it would automatically inherit the same ACEs).

Granting permissions to a file or folder

Now, things are starting to heat up. Let’s set permissions and add some to other users in our Active Directory domain with the /grant switch. With the following command, we’ll give Billy Reinders (breinders) read-only (R) permissions to the Excellent.txt file.

icacls Excellent.txt /grant reinders\breinders:R /t /c
Granting permissions to a file for a user with icacls
Granting permissions to a file for a user

The previous command here was completed successfully; I then validated my changes by checking permissions – we now see ‘REINDERS\breinders’ has read-only (R) permissions. And, because we do NOT see an ‘I’ listed, we know it is not inherited, it is explicit.

Just to remind you, the ‘/t’ switch is used to set the permissions recursively on the entire folder tree. The ‘/c’ switch tells the command to keep going in case it encounters any errors.

Removing permissions to a file or folder

Instead of using the /grant switch to give/add permissions, we use the /remove switch to remove permissions from an ACE. Let’s go ahead and remove Billy’s rather short-lived access to the Excellent.txt file.

icacls Excellent.txt /remove:g reinders\breinders /t /c
Using the /remove switch with icacls to remove permissions to a file for a user
Using the /remove switch to remove permissions to a file for a user

Here, we are using the ‘/remove:g’ switch to remove the permission that was granted previously to Billy Reinders. I ran the command again to verify and you’ll see the ACL for Billy is gone. Excellent! 😉

Denying permissions to a file or folder

Generally, you’ll want to avoid using explicit ‘deny’ permissions due to the complexity it permeates into your overall permission infrastructure. For the majority of situations, you can rely on an implicit deny, the default, to handle these circumstances.

If a user is not listed in an ACL and the user is not a member of any group(s) listed in the ACL, that user is assumed (correctly) by Windows to have NO permissions on that object. However, the following example illustrates how out of control this can become – if a user is a member of two groups, and one group is granted access while the other group is denied, that user will be denied. That, in and of itself makes sense, but it can get very convoluted in trying to troubleshoot this sort of thing.

However, if you want to add a deny permission explicitly, you can use the general ‘/deny’ switch to accomplish this.

icacls Download /deny reinders\breinders:(OI)(CI)F /t /c
Using the /deny switch with icacls to put explicit deny permissions on a file or folder structure
Using the /deny switch to put explicit deny permissions on a file or folder structure

There you can see the command I ran; it was completed successfully. I then checked the Security tab for the Download folder – you can see that Billy has Deny permissions on the object and all its contents.

How to reset the ACL for an object

I can’t tell you how many file server migrations or movements of large amounts of file projects I’ve been involved in where I just needed to start from scratch. This invaluable step includes resetting the ACLs on an object in case things get too far gone, or you succumb to a bad idea after being up all night. Maybe a malware attack crippled an entire HR directory that NEEDS to get resolved ASAP. Thankfully, you can use the ‘/reset’ flag to reset the permissions to the default.

icacls Download /reset /t /c


Right after I re-granted Billy ‘RW’ rights to the Download folder and its contents, I ran the reset command. As you can see, his name is again absent from the ACL on the Security tab. Nice and easy.

How to save and restore ACLs

A wonderfully powerful feature included with icacls is the ability to backup and restore the ACL of an object to a file for safekeeping. Before you start a large script that changes or resets permissions on millions of files, you can first save the current state of those millions of files’ ACLs to a single file.

If you notice partway through your script that you made a syntax error maybe, you can abort it, then restore the state of the ACLs for the entire tree with one run of the command using the ‘/restore’ parameter! Let’s give it a go!

icacls Download /save Download_ACL_Backup /t
What the backed-up text file looks like with all the ACLs - wowzers!
What the backed-up text file looks like with all the ACLs – wowzers!

This will save the entire ACL tree of the Download folder into a single file named ‘Download_ACL_Backup’. Now, I highly recommend you NOT fiddle with that text file. Yes, it looks like some crazy stuff like Linux or something. 🙂 Just kidding.

Here is the current state of the Download folder.

The 'Download' folder before Junior performs his ill-advised permissions changes...
The ‘Download’ folder before Junior performs his ill-advised permissions changes…

Now, let’s suppose a junior administrator grants Billy Reinders full access to the location. Let’s also assume it contains HR data that Billy should NOT have access to.

icacls Download /grant reinders\breinders:F /t /c
Our Junior Admin has granted Billy Reinders Full access to the location
Our Junior Admin has granted Billy Reinders Full access to the location

After the command, I check again and see that Billy has full, explicit control in this folder. In one fell swoop, I can be assumed the permissions will revert to defaults with one run of this command.

icacls Download /reset /t /c
After running the /reset switch, we see Billy no longer has explicit access!
After running the /reset switch, we see Billy no longer has explicit access!

After running the reset command, you can see that his name is AGAIN removed from the ACL. He no longer has full access to the folder. Reminder – this will scan the entire folder hierarchy.

Tip: Throughout this scenario, you may have realized that Billy does have read-only access because the built-in Users group (of which Billy is a member) has default Read and Execute permissions. Just a side note.

How to manage Windows integrity levels with icacls

There’s a lesser-known feature built into Windows called mandatory access control (MAC). It has been around for quite a while. However, Microsoft introduced mandatory integrity control (MIC) in Windows Vista/Windows Server 2008.

Permissions are defined by policy-based fixed rules and generally cannot be overridden by users. It is generally referred to as Windows integrity control (WIC). The integrity level is used to determine the level of protection of an object in Windows. Essentially, you always want to make sure you have the right permissions for your users.

I won’t go into great detail here, but I can show you a few examples of how to use the icacls command with it. If we create a new folder, Test, in the Download directory, we can adjust its integrity level to ‘h’igh.

icacls Test /setintegritylevel h

To make a long story short, the high level is synonymous with the permissions needed to run a task or process as an administrator (admin rights). So, even if Billy Reinders had Full Control to this folder, unless he was somehow granted magic administrator permissions, AND was able to run File Explorer as an admin (he can’t…), he would NOT be able to access this folder and its contents.

So, essentially it’s another layer of security and protection you could use to protect highly sensitive data.

How to manage permission inheritance with icacls

We can also use the icacls command to view and modify the inheritance permission on files and folders. This allows us to set explicit permissions on one folder while keeping the remaining folders set to auto-accept the parent container’s ACLs.

Disable inheritance on files and folders

We can disable inheritance on a file or folder by using the ‘/inheritance:d’ parameter. In my example, we have an Install folder in the Download folder. You can see here that the folder is set to inherit all of its permissions from above.

icacls Download
Disabling inheritance on the Install folder leaving only explicit ACEs
Disabling inheritance on the Install folder leaving only explicit ACEs

Let’s remove the inheritance on the Install folder.

icacls Install /inheritance:d /t /c
inheritance has been disabled as the 'Enable inheritance' button/toggle is available
We can see that inheritance has been disabled as the ‘Enable inheritance’ button/toggle is available

There you go. You will notice all the ‘(I)’ entries are gone. These are now all explicit permissions. And you can see below verification from the GUI that the ‘Enable inheritance’ button is available because we disabled it.


The most intriguing aspect of icacls to me is the robustness of being able to script with this command complicated projects. And, again, not having to worry about the reliability of File Explorer in case it runs into an error, it crashes, things like that.

I hope you learned more about using the command line to modify permissions. Please leave a comment or question below. Thank you!

Related Article: