getfacl shows the access control list on a file, including named users, named groups and the effective-rights mask. Plain owner and group bits never reveal any of that. The examples use getfacl from acl version 2.3.2-1build1.1. Allow about ten minutes.
You need a shell and read access to the paths you are checking. Nothing in this guide changes permissions or restarts a service.
Start with a path you can read. Use -p when you want the full path in the header:
$ getfacl -p /srv/project/report.txt
# file: /srv/project/report.txt
# owner: alice
# group: analysts
user::rw-
group::r--
other::---
user:bob:r-- grants rights to Bob specifically. A named group works the same way for a group.# lines describe the file, owner and group; they are not ACL entries themselves.Checkpoint: confirm the path, owner and group are the ones you meant. If the command says permission is denied, do not jump straight to sudo. Check the containing directory and the file first:
$ namei -l /srv/project/report.txt
$ ls -l /srv/project/report.txt
Reading an ACL needs search access to the containing directory, much like reading the file itself. Use elevated privileges only when your access policy allows it and the diagnostic genuinely needs them:
$ sudo getfacl -p /srv/project/report.txt
Extended ACLs usually include a mask:: entry. It caps the effective rights of named users, named groups and the owning group. It does not limit the file owner or the other:: entry:
$ getfacl -p /srv/project/shared.txt
# file: /srv/project/shared.txt
# owner: alice
# group: analysts
user::rw-
user:bob:rwx #effective:r--
group::r-- #effective:r--
group:reviewers:r-x #effective:r--
mask::r--
other::---
Bob's ACL entry says rwx, but the mask is r--, so his effective rights are read-only. The same cap applies to the owning group and the named group. Do not read the text before #effective: as what a user actually gets.
By default, effective-rights comments appear only when they differ from the entry. Use -e to show every effective-rights comment, and -E to suppress them. Suppressing the comments changes the display, not the ACL:
$ getfacl -E -p /srv/project/shared.txt
$ getfacl -e -p /srv/project/shared.txt
A directory can carry a default ACL that new children inherit, separate from its access ACL. Ask for it explicitly with -d:
$ getfacl -p -d /srv/project
# file: /srv/project
# owner: alice
# group: analysts
user::rwx
group::r-x
mask::r-x
other::---
The exact entries depend on the directory. A regular file cannot have a default ACL, and a directory without one reports that no default ACL exists. That is a useful result: it means there is no directory-level default to inspect, not that the command silently found an empty policy.
Tip: For the normal combined view, omit -d: getfacl prints the access ACL and, when present, the directory's default ACL together. Use -a for the access ACL alone only when a script or comparison needs to exclude defaults.
Without -p, getfacl strips leading slashes from absolute paths and may print a notice on standard error. It still read the same file, but the stripped output can confuse anyone copying it later. Keep -p in reports and troubleshooting commands.
Names are easier to read, but they can change or be missing on another host. Use -n for numeric user and group IDs when comparing machines or preserving evidence:
$ getfacl -n -p /srv/project/shared.txt
# file: /srv/project/shared.txt
# owner: 1001
# group: 1008
user::rw-
group::r--
other::---
Use -c to drop the first three comment lines when a consumer only needs the ACL entries themselves. Do not use it as a substitute for recording the file's identity; capture the path separately in your report.
-R reads a directory tree recursively. The default walk follows a symbolic-link argument but skips symbolic links found below the starting directory. Make that boundary explicit in scripts: -P forces a physical walk, -L follows symbolic links to directories. Both only affect recursive operation:
$ getfacl -R -P -p /srv/project > project-acls.txt
$ sed -n '1,24p' project-acls.txt
Redirection creates or truncates project-acls.txt. Pick a new report path, or protect an existing one, before you rely on that form:
$ getfacl -R -P -p /srv/project > project-acls.txt.new
$ test -s project-acls.txt.new && mv project-acls.txt.new project-acls.txt
The first command only reads the tree. The second replaces the old report only if the new file is non-empty. If it fails, inspect the error and keep the previous report; remove the leftover .new file later, once you have checked it is disposable.
A single dash tells getfacl to read file names from standard input, handy when another command has already picked the paths:
$ printf '%s\n' /srv/project/report.txt /srv/project/shared.txt | getfacl -p -
Put -- before a path that starts with a dash, so it cannot be mistaken for an option:
$ getfacl -p -- ./-draft.txt
On a file system without ACL support, getfacl shows the permissions represented by the traditional mode bits. That output is still useful, but it does not prove extended named entries are available. If a report needs comparing later, record the command, the full path and whether -n, -p or -R was used.
-p for full paths and -n when numeric identities mattered.-P or -L on purpose and did not overwrite a useful report by accident.