Skip to content
shellmap

setfaclGrant per-user/per-group ACLs, default-ACL inheritance, mask cap. icacls / Set-Acl Windows across all 5 shells

Equivalents in every shell

Bashunix
setfacl -m u:alice:rwx file.txt

`-m` modify (add/update entry), `-x` remove an entry, `-b` strip ALL extended ACLs (keep only POSIX base). The entry spec uses the same syntax as `getfacl` output: `u:USERNAME:PERMS`, `g:GROUPNAME:PERMS`, `m:PERMS` (mask), `o:PERMS` (other). PERMS can be octal-style `rwx` or numeric-style `7`. Multiple in one call: `setfacl -m u:alice:rwx,g:devs:rx file.txt`. Recursive: `-R`. From a file: `setfacl --restore=backup.acl` (paired with `getfacl -R . > backup.acl` for backup/restore).

Zshunix
setfacl -m u:alice:rwx file.txt
Fishunix
setfacl -m u:alice:rwx file.txt
PowerShellwindows
$acl = Get-Acl file.txt; $rule = New-Object Security.AccessControl.FileSystemAccessRule "alice", "FullControl", "Allow"; $acl.SetAccessRule($rule); Set-Acl file.txt $acl

Windows-only — pwsh on Linux/macOS has no `Set-Acl` for POSIX ACLs (shell out to `setfacl`). The Windows model is DACL with explicit allow/deny ACEs — fundamentally different from POSIX. `FileSystemRights` enum is a `[Flags]` bitmask; common values: `Read`, `Write`, `ReadAndExecute`, `Modify`, `FullControl`. `InheritanceFlags`: `ContainerInherit`, `ObjectInherit`. `PropagationFlags`: `None`, `InheritOnly`, `NoPropagateInherit`.

cmd.exewindows
icacls file.txt /grant "alice:(F)"

`/grant USER:PERMS` adds an ALLOW ACE. PERMS shortcuts: `(F)` Full, `(M)` Modify, `(RX)` ReadAndExecute, `(R)` Read, `(W)` Write. `/grant:r` REPLACES existing grants (vs `/grant` which ADDS). `/deny USER:PERMS` adds a DENY ACE. `/remove USER` strips the user's ACEs entirely. Recursive: `/t`. Inheritance flags: `(OI)` ObjectInherit, `(CI)` ContainerInherit, `(IO)` InheritOnly. Combined example: `icacls dir /grant "alice:(OI)(CI)(M)" /t`.

Worked examples

Grant a specific user read+write access

Bash
setfacl -m u:alice:rw file.txt
Fish
setfacl -m u:alice:rw file.txt
PowerShell
$acl = Get-Acl file.txt; $acl.SetAccessRule((New-Object Security.AccessControl.FileSystemAccessRule "alice","Modify","Allow")); Set-Acl file.txt $acl
cmd.exe
icacls file.txt /grant "alice:(M)"

Set a default ACL on a directory (inherited by new children)

Bash
setfacl -d -m u:alice:rwx dir/
Fish
setfacl -d -m u:alice:rwx dir/
PowerShell
$acl = Get-Acl dir; $acl.SetAccessRule((New-Object Security.AccessControl.FileSystemAccessRule "alice","FullControl","ContainerInherit,ObjectInherit","None","Allow")); Set-Acl dir $acl
cmd.exe
icacls dir /grant "alice:(OI)(CI)(F)"

Remove all extended ACLs (back to plain POSIX mode bits)

Bash
setfacl -b file.txt
Fish
setfacl -b file.txt
PowerShell
$acl = Get-Acl file.txt; $acl.SetAccessRuleProtection($true, $false); $acl.Access | ForEach-Object { $acl.RemoveAccessRule($_) }; Set-Acl file.txt $acl
cmd.exe
icacls file.txt /reset

Gotchas

  • After adding an explicit user/group entry, the MASK is auto-recalculated to cover all granted permissions. So `setfacl -m u:alice:rwx file` may bump the mask from `r--` to `rwx` automatically — which then grants the GROUP entry write too (because the mask caps every explicit entry the SAME way). To pin the mask explicitly: `setfacl -m m::r-- file` after the user grant. Use `--mask` or `-n` (no-mask-recalc) to preserve the existing mask: `setfacl -n -m u:alice:rwx file`. The auto-recalc behavior is mostly safe but bites when you intentionally want to cap a user's effective permissions.
  • **Default ACLs propagate to NEW children — only on directories**: `setfacl -d -m u:alice:rwx dir/` sets the DEFAULT ACL on `dir` — the template for new files/subdirs created INSIDE. Existing files inside `dir/` are NOT retroactively updated. To apply to existing files too: a separate `setfacl -R -m u:alice:rwx dir/` 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". To strip default ACL only (keep access ACL): `setfacl -k dir/`.
  • macOS has NO `setfacl` — NFSv4 ACLs use `chmod +a / +a# / -a / -a#`. Examples: `chmod +a "alice allow read,write" file` (add ACE), `chmod -a "alice deny delete" file` (remove ACE), `chmod +a# 0 "alice deny read" file` (insert at position 0 — ORDER MATTERS in NFSv4 ACLs, first-match-wins). `ls -le` shows them. Scripts assuming `setfacl` works on macOS fail at the binary-not-found level. Cross-platform: `if [[ "$(uname)" == "Darwin" ]]; then chmod +a "alice allow read,write" file; else setfacl -m u:alice:rw file; fi`.
  • Backups and ACL preservation — `cp`, `tar`, `rsync` ALL drop ACLs by default. The xattr-preserving forms: `cp --preserve=all SRC DST`, `tar --acls --xattrs -cf archive.tar dir/` (note: `--acls` is a separate flag from `--xattrs`), `rsync -aAX SRC DST` (`-A` ACLs, `-X` other xattrs). For backup/restore of just the ACL state of a tree: `getfacl -R . > /tmp/acls.bak` then restore on the target: `setfacl --restore=/tmp/acls.bak`. NFSv3 cannot preserve POSIX ACLs (the protocol has no extension for them); NFSv4 has its own ACL model with limited round-trip fidelity to POSIX.
  • Filesystem support varies — POSIX.1e ACLs work on ext2/3/4, xfs, btrfs, zfs (with `aclmode=passthrough` set). NOT supported on: vfat, exfat, ntfs (kernel driver), iso9660. Many bind-mounts and tmpfs work; some sysfs/procfs do not. To check: `mount | grep "$(df -P /path | tail -1 | awk '{print $1}')"` and look for `acl` in the options — if missing, `mount -o remount,acl /` enables it. On btrfs/zfs/xfs the ACL support is "always-on" — no mount option needed. `getfacl` on a non-ACL-capable filesystem returns the POSIX base bits only and `setfacl` fails silently or with "Operation not supported".

WSL & PowerShell Core notes

pwshpwsh 7 on Linux: no Set-Acl equivalent for POSIX ACLs — shell out to `setfacl`. pwsh on Windows: `Set-Acl` works on NTFS ACLs (different model). Cross-platform pattern: `if ($IsLinux) { & sudo setfacl -m "u:alice:rwx" $file } elseif ($IsMacOS) { & chmod +a "alice allow read,write" $file } else { Set-Acl $file $acl }`.
WSLWSL Linux `setfacl` works on the WSL filesystem (`~`, `/home`, `/`). On Windows-mounted paths (`/mnt/c/...`) `setfacl` either no-ops or returns "Operation not supported" — NTFS doesn't implement POSIX.1e ACLs. To modify NTFS ACLs from WSL: shell out to `icacls.exe` via interop (`/mnt/c/Windows/System32/icacls.exe "C:\path\file" /grant "alice:(M)"`), or `pwsh.exe -Command "Set-Acl ..."`.

Related commands