Skip to content
shellmap

View ACLs and extended file permissions

Inspect the full access-control list of a file — beyond the POSIX nine-bit `rwxrwxrwx` mode — to see per-user / per-group grants, the ACL mask, default (inherited) ACLs, and the audit (SACL) entries that `ls -l` will not show.

How to view acls and extended file permissions in each shell

Bashunix
getfacl file.txt

`getfacl` (from `acl` package — `apt install acl` / `dnf install acl`) prints POSIX.1e ACLs stored as the `system.posix_acl_access` xattr. The output shows `user::`, `group::`, `other::` (the nine POSIX bits), plus any explicit `user:alice:rwx` / `group:devs:rx` entries and a `mask::` line. If `getfacl file` shows only the three POSIX lines and NO `mask::`, the file has no extended ACL — `ls -l` is enough.

Zshunix
getfacl file.txt
Fishunix
getfacl file.txt
PowerShellwindows
(Get-Acl file.txt).Access | Format-Table IdentityReference, FileSystemRights, AccessControlType, IsInherited -AutoSize

Windows-only — pwsh 7 on Linux/macOS has no `Get-Acl` (use `getfacl` via the system shell). `.Access` is the DACL (Discretionary ACL — grants/denies). For audit entries (SACL — who triggered an access-attempt log), use `(Get-Acl file -Audit).Audit` and run as Administrator. `IsInherited=True` marks ACEs that came from a parent directory.

cmd.exewindows
icacls file.txt

`icacls FILE` prints the DACL in a compact one-line-per-principal form: `Everyone:(R)` (read), `BUILTIN\Administrators:(F)` (full), `(OI)(CI)` flags for inheritance (ObjectInherit / ContainerInherit). Add `/q` to suppress the success line. For an inheritance-tree view of a directory: `icacls dir /t /q` prints every child whose ACL differs from the parent.

Equivalents listed for Bash, Zsh, Fish, PowerShell, cmd.exe.

Gotchas & notes

  • **POSIX ACL vs NFSv4 ACL — Linux and macOS use fundamentally different models**. Linux (ext4, xfs, btrfs) implements POSIX.1e draft ACLs: a flat list of `user:` / `group:` / `mask:` / `other:` entries, evaluated additively. macOS (APFS, HFS+) implements **NFSv4 ACLs**: an *ordered* list of ALLOW / DENY ACEs evaluated top-down — the first match wins, and a DENY ACE before an ALLOW ACE for the same right blocks it. `ls -le` on macOS shows entries like `0: group:everyone deny delete`; the *number* is the ordinal that matters. Tools don't cross over: macOS has no `getfacl`; Linux has no `chmod +a`. Files SMB-shared between the two collapse extended ACLs into mode bits on transit.
  • **The ACL mask — POSIX ACL's silent permission cap**: when a Linux file has an extended ACL, `getfacl` shows a `mask::rwx` line. The mask ANDs with every explicit user/group entry to give the EFFECTIVE permissions. So `user:alice:rwx` + `mask::r--` → alice only gets `r--` in practice. `getfacl` prints `#effective:r--` next to each masked entry. `chmod g+w file` MODIFIES the mask, not the group entry — this confuses people coming from non-ACL Linux. To reset the mask: `setfacl -m m::rwx file`. Always read the mask line before debugging "but I granted alice write — why is it failing?"
  • **Default ACLs propagate to NEW children — only on directories**: `getfacl -d dir/` prints the *default* ACL (inherited by files and subdirs created INSIDE `dir`). The default ACL doesn't affect `dir` itself — it's a template for new entries. Example: `setfacl -d -m u:alice:rwx /srv/shared` means every file alice or anyone creates in `/srv/shared` gets `user:alice:rwx` automatically. Existing files are NOT retroactively updated — only newly-created ones. To apply to existing files too: a separate `setfacl -R -m u:alice:rwx /srv/shared` pass. The combination of access ACL + default ACL is the POSIX-ACL way to do "team folder where everyone keeps access regardless of who created the file".
  • **Windows ACEs: ordering matters AND inheritance is flag-driven**. `icacls` prints each ACE as `Principal:(Flag1)(Flag2)(Right)`. Flags: `(OI)` ObjectInherit — applies to files in this dir; `(CI)` ContainerInherit — applies to subdirs; `(IO)` InheritOnly — *only* propagates, doesn't apply to this object; `(NP)` NoPropagate — children inherit but grandchildren don't; `(I)` Inherited — this ACE came from a parent (you can't edit it on the child; edit the parent or break inheritance). Rights: `(F)` Full, `(M)` Modify, `(RX)` ReadAndExecute, `(R)` Read, `(W)` Write. DENY ACEs precede ALLOW ACEs in the printed order — Windows evaluates explicit DENY before inherited ALLOW, so a deny on the file beats an allow from the parent. `icacls dir /verify` checks for orphaned SIDs from deleted accounts.
  • **Cross-platform pitfall — `ls -l` lies when ACLs are present**: on Linux, files with a POSIX ACL show a `+` after the mode bits (`-rw-r--r--+ 1 alice ...`) — that's your only `ls`-visible cue to run `getfacl`. On macOS, files with an NFSv4 ACL show an `@` for xattrs or a `+` for ACLs — `ls -le` decodes them. Windows: `dir` shows NO ACL hint at all; the mode column is fake compatibility. ALWAYS check for the `+`/`@` indicator before assuming `chmod 755` is the full picture. For scripts: `getfacl --absolute-names --skip-base file` outputs ONLY the extended entries (empty output = no ACL beyond POSIX bits — safe to ignore).

Related commands

Related tasks