Permissions are not the whole story on an ext filesystem, and lsattr reads what ls -l cannot show. It surfaces bits like immutable or append-only that quietly change how a file behaves. This guide covers a single file, hidden entries, directories versus their contents, recursive output, long names, and the project and generation numbers people forget exist. Ten minutes, a shell, and the e2fsprogs package; everything here is read-only and normally needs no elevated privileges.
This machine has lsattr from e2fsprogs 1.47.0-2.4~exp1ubuntu4.1, and the utility itself reports version 1.47.0, dated 5 February 2023. Your distribution may package something different, so check before trusting output details in a script:
$ command -v lsattr
/usr/bin/lsattr
$ lsattr -V
lsattr 1.47.0 (5-Feb-2023)
The documented syntax is lsattr [-RVadlpv] [files...]. There is no GNU-style --help on this build; read man lsattr instead.
$ lsattr /path/to/file
--------------e------- /path/to/file
That string is a fixed set of character positions: a letter means the attribute is set, a hyphen means it is not, and which letters are possible depends on your filesystem and kernel. The e above just means the file uses extents, which is normal on ext4. Do not recite the attribute letters from memory when a security or recovery decision rides on them; man chattr documents what each one means, since lsattr only reads them.
Checkpoint: a successful run just prints the path back at you. It has read metadata, nothing more; it cannot set, clear or repair an attribute.
Without an option, a directory is treated as a container and its entries get listed. Use -d to treat the directory inode itself like an ordinary file:
$ lsattr -d /path/to/directory
--------------e------- /path/to/directory
This is a genuinely common source of wrong conclusions: seeing attributes on files inside a directory tells you nothing about the directory's own inode. And -d never recurses, it only ever reports the one entry:
$ lsattr /path/to/directory
--------------e------- /path/to/directory/file-a
--------------e------- /path/to/directory/file-b
$ lsattr -d /path/to/directory
--------------e------- /path/to/directory
-a includes names starting with a dot, plus the conventional . and .. entries:
$ lsattr -a /path/to/directory
--------------e------- /path/to/directory/.
--------------e------- /path/to/directory/file-a
--------------e------- /path/to/directory/.hidden
-----------I--e------- /path/to/directory/..
Order and exact attributes will vary; the point is that hidden names show up at all. A shell glob like /path/to/directory/* is not a substitute, since it normally skips dotfiles entirely.
The compact string scans fast but reads badly to someone else. -l spells it out:
$ lsattr -l /path/to/file
/path/to/file Extents
Easier to hand to a colleague, harder to parse in a script. Pick one form for automation and test it against the exact e2fsprogs version you deploy; do not mix the readable form into a parser built for compact positions.
-p shows the project number, -v the version or generation number, both separate from the attribute letters themselves:
$ lsattr -pv /path/to/file
0 2407015937 --------------e------- /path/to/file
These are filesystem metadata, not timestamps and not any kind of backup history. Zero or an unfamiliar value can simply mean the field is unset or unsupported on this filesystem. Record the full line if you are comparing before and after maintenance work.
-R recurses, printing a directory heading before each subdirectory's contents:
$ lsattr -R /path/to/tree
--------------e------- /path/to/tree/file-a
/path/to/tree/subdirectory:
--------------e------- /path/to/tree/subdirectory/file-b
This can produce a lot of output fast, and may hit directories you cannot read. If you redirect it to a report, check the destination name first: > truncates an existing file before lsattr even starts.
$ lsattr -R /path/to/tree > attributes.txt
$ test -s attributes.txt && echo 'attribute report created'
Warning: if an old report matters, use a fresh filename such as attributes-$(date +%Y%m%d).txt, or copy it first. lsattr itself changes no filesystem attributes, but careless redirection can destroy a report you needed. Deleting an unwanted one afterwards is a separate, irreversible step that has nothing to do with lsattr.
Command errors on a path? Check existence and readability first, do not jump straight to sudo:
$ ls -ld /path/to/file
$ test -r /path/to/file && echo readable
$ lsattr /path/to/file
lsattr and e2fsprogs versions are installed.-d.-a when auditing a directory.-l, -p and -v when the compact string or the metadata numbers needed more context.