On this page
ls
ls lists the contents of a directory. It is the command you reach for to answer "what is in here?" — and, with the right options, "who owns these files, how big are they, and when were they last changed?".
ls [options] [file...]
Each file is a directory to list the contents of, or a single file to report on. With no file argument, ls lists the directory you are currently in.
$ ls
build.sh notes.txt projects
The default listing
Run on its own, ls prints the names of the entries in a directory and nothing else. Three rules shape that default:
- Hidden entries are skipped. A name beginning with a dot (
.config,.cache) is hidden.lsleaves hidden entries out unless you ask for them with-aor-A. - Entries are sorted by name. Alphabetical order, case-sensitive. Other sort orders are available.
- The layout adapts to where output goes. When
lsis writing to a terminal it arranges names into columns sized to the terminal width. When output is redirected to a file or a pipe it prints one name per line, so the result is easy for another program to read.
Everything past this default is opt-in. The rest of this page is the options, grouped by what they do.
The long format
-l (or --long) switches ls into the long format: one entry per line, each with its mode, owner, size, modification time, and name.
$ ls -l
total 28
d-- S-1-5-21-9f3a-1c4e-7b20-1001 4096 May 14 09:12 projects
-x- S-1-5-21-9f3a-1c4e-7b20-1001 8344 May 16 17:40 build.sh
--- S-1-5-21-9f3a-1c4e-7b20-1001 219 May 15 11:03 notes.txt
--+ S-1-5-18 12048 May 10 22:15 policy.db
The total line at the top reports the combined disk space used by the listed files, measured in blocks.
Each entry line has five columns: mode, owner, size, modification time, name. There is no permission-bits column and no group column — the reason is below.
The mode column
The mode column is three characters: [type][executable][protected].
The first character is the file's type:
| Character | Type |
|---|---|
- |
Regular file |
d |
Directory |
l |
Symbolic link |
p |
Named pipe (FIFO) |
s |
Socket |
c |
Character device |
b |
Block device |
The second character is the executable mark. It is x when the entry is a regular file that is marked as an executable, and - otherwise (it is always - for directories, links, and other non-regular entries).
The executable mark describes the file, not your relationship to it. x means "this file is runnable code." It does not mean that you, specifically, are allowed to run it — whether a given principal may execute a file is a separate access decision made against the file's security descriptor. A file can show x and still be one you cannot run, and the reverse. See Access decisions for how execution is actually authorised.
The third character is the protected mark. It is + when the file's access control is inheritance-protected, and - otherwise.
A - here means the file's access control is inherited from the directory it lives in: it tracks its parent. A + means the file's access control has been set deliberately and locked, so it no longer tracks the parent directory. The + is the signal that someone has tailored this file's security on purpose. See Inheritance.
So in the example above: projects is a directory (d--); build.sh is an executable file (-x-); notes.txt is an ordinary file inheriting its security from its directory (---); and policy.db is an ordinary file whose access control has been protected (--+).
Why there are no permission bits
A long listing does not carry a fixed block of permission characters. On Peios, what a principal may do to a file is decided by the file's security descriptor — a record that can contain any number of entries granting or denying specific rights to specific principals. There is no small, fixed set of bits that captures that, so ls -l does not pretend there is.
The mode column tells you the file's type and two facts about it (is it executable, is its security protected). To see who may do what, look at the security descriptor itself with stat or the dedicated security tooling. The concepts are in Security descriptors.
The owner column
The owner column is the SID of the file's owner — shown in full, in the S-1-… form. ls does not translate SIDs into account names; it prints the identifier exactly as the security descriptor stores it. A well-known owner such as the system itself appears as its fixed SID (S-1-5-18); an ordinary account appears as a longer domain-style SID.
For what a SID is and how to read one, see SIDs. For what "owner" means and what it grants, see Ownership.
If ls cannot read a file's descriptor — for a dangling symlink, say — the owner column shows ? and the mode column shows the type character followed by ??.
Choosing what to list
By default ls shows non-hidden entries, and for a directory argument it shows the directory's contents. These options change that.
| Option | Effect |
|---|---|
-a, --all |
Show hidden entries too, including . (the directory itself) and .. (its parent). |
-A, --almost-all |
Show hidden entries, but leave out . and ... |
-d, --directory |
List a directory as an entry in its own right, instead of listing its contents. Useful with -l to see a directory's own owner and mode. |
-R, --recursive |
Descend into every subdirectory and list it too. |
-B, --ignore-backups |
Skip entries whose name ends in ~. |
--ignore=PATTERN |
Skip entries whose name matches the shell pattern. May be given more than once. |
--hide=PATTERN |
Like --ignore, but overridden by -a or -A — so a hide rule can be cancelled by asking to see everything. |
Sorting
ls sorts by name by default. These options change the sort key; -r reverses whatever order is in effect.
| Option | Sort order |
|---|---|
-t |
By modification time, newest first. |
-S |
By size, largest first. |
-X |
By file extension, alphabetically. |
-v |
By version: runs of digits in the name sort numerically, so f2 comes before f10. |
-U |
No sorting at all — entries appear in the order the directory stores them. Fast for very large directories. |
-r, --reverse |
Reverse the current sort. |
--sort=WORD |
Choose the sort key by name: none, time, size, extension, version, or width. |
--group-directories-first |
List directories before other entries, with each group sorted normally. |
Output layout
When several entries fit on a line, ls has to decide how to arrange them.
| Option | Layout |
|---|---|
-C |
Columns, filled top-to-bottom. The default when writing to a terminal. |
-x |
Columns, filled left-to-right (across the rows) instead. |
-1 |
One entry per line. The default when output is not a terminal. |
-m |
All entries on as few lines as possible, separated by commas. |
-l, --long |
The long format described above. |
--format=WORD |
Choose the layout by name: across, commas, horizontal, long, single-column, or vertical. |
-w, --width=COLS |
Assume the terminal is COLS columns wide instead of detecting it. 0 means unlimited. |
File-type indicators and colour
These options make a listing easier to scan by marking entries with a symbol or a colour.
| Option | Effect |
|---|---|
-F, --classify |
Append a type symbol to each name: / for a directory, @ for a symlink, ` |
--file-type |
The same, but without the * on executables. |
-p |
Append only the / on directories. |
--indicator-style=WORD |
Choose the indicator set: none, slash, file-type, or classify. |
--color[=WHEN] |
Colour entries by type. WHEN is auto (colour only when writing to a terminal — the usual choice), always, or never. |
The colours ls uses are configurable. dircolors generates the colour settings and explains how to install them.
File sizes
In the long format, and with -s, sizes are printed in bytes by default. These options rescale them.
| Option | Effect |
|---|---|
-h, --human-readable |
Print sizes with a unit suffix — 4.0K, 234M, 56G — using powers of 1024. |
--si |
Like -h, but using powers of 1000, so the suffixes are decimal. |
-s, --size |
Print the disk space each entry occupies, in blocks, before its name. |
-k, --kibibytes |
Use 1024-byte blocks for the size figures and directory totals. |
--block-size=SIZE |
Scale every size by SIZE (for example --block-size=1M to count in megabytes). |
Timestamps
The long format shows the modification time by default. These options change which timestamp is shown — and, when sorting by time, which one is sorted on.
| Option | Timestamp |
|---|---|
-u |
Access time — when the file was last read. |
-c |
Status-change time — when the file's metadata last changed. |
--time=WORD |
Choose the timestamp by name: atime/access, ctime/status, mtime/modification, or birth/creation. |
--time-style=STYLE |
Choose the date format: full-iso, long-iso, iso, locale, or +FORMAT for a custom layout. |
--full-time |
Shorthand for the long format with --time-style=full-iso — a complete, unabbreviated timestamp. |
Symbolic links
By default ls reports on a symbolic link itself — its type is l, its size is the length of the link text. These options make it report on the link's target instead.
| Option | Effect |
|---|---|
-L, --dereference |
Always report on the file a link points to, not the link. |
-H, --dereference-command-line |
Dereference only the links named directly on the command line, not links found inside a listed directory. |
--dereference-command-line-symlink-to-dir |
Dereference a command-line link only when it points to a directory. |
readlink and realpath are the dedicated tools for inspecting and resolving links.
Other options
The long-tail options, each in one line.
| Option | Effect |
|---|---|
-i, --inode |
Print each entry's index number (its inode number). |
-Z, --context |
Print each entry's security context. Available only when the build enables it. |
-b, --escape |
Print non-printable characters in names using C-style backslash escapes. |
-q, --hide-control-chars |
Replace non-printable characters in names with ?. The default when writing to a terminal. |
--show-control-chars |
Print names verbatim, control characters and all. |
-N, --literal |
Print names exactly, with no quoting. |
-Q, --quote-name |
Wrap each name in double quotes. |
--quoting-style=WORD |
Choose the quoting scheme: literal, shell, shell-always, shell-escape, c, escape, and others. |
-T, --tabsize=COLS |
Assume tab stops every COLS columns when laying out output. |
-f |
List everything, unsorted, including hidden entries — equivalent to -aU. Also turns colour off unless --color is given explicitly. |
--hyperlink[=WHEN] |
Emit terminal hyperlinks for file names, so a capable terminal can make them clickable. |
-D, --dired |
Emit extra position markers designed for the Emacs dired editing mode. |
--zero |
End each line with a NUL character instead of a newline, and list one entry per line. |
Exit status
| Code | Meaning |
|---|---|
0 |
Success — everything requested was listed. |
1 |
A minor problem — for example, a named file could not be accessed. The rest of the listing still printed. |
2 |
A serious problem — for example, a directory could not be read, or an option was invalid. |