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
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.
getfacl file.txtgetfacl file.txt(Get-Acl file.txt).Access | Format-Table IdentityReference, FileSystemRights, AccessControlType, IsInherited -AutoSizeWindows-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.
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
- Change file permissions— Modify read/write/execute permissions on a file or directory.
- Change the owner of a file or directory— Reassign a file or directory to a different user (and optionally group) — for fixing permission errors after copying files between users, after extracting tarballs as root, or when handing data over to a service account.
- Find files by permission bits— Search a directory tree for files matching specific permission bits — world-writable files for a security audit, SUID/SGID binaries for a post-CVE sweep, or files with exactly `0644` to verify a deployment.